EOJ数据结构1088 dijkstra算法 优先队列实现

用优先队列实现了dijkstra算法,写了两个函数说不定其他题也能用用,dijkstra(start,n)是找到从start到n的所有点的最短路径权值,dijkstra2(start,end,n)是在n个点中找到start到n的最短路径,输出都是最短路径以及最短路径数和一条最短路径

代码如下

#include<bits/stdc++.h>
#define maxn 110
#define inf 1e9
using namespace std;

struct node{
    int sign;int weight;
};

class cmp{
    public:
        bool operator()(const node& x,const node& y){
            return x.weight>y.weight;
        }
};

priority_queue<node,vector<node>,cmp>q;

int a[maxn][maxn];
int weight[maxn];
bool sign[maxn];

int num[maxn];//count num
int num2[maxn][maxn];//store the same distance but different road form a to b

void init(){
    for(int i=0;i<maxn;i++){
        for(int j=0;j<maxn;j++)a[i][j]=inf;
    }
}

node mp(int sign,int weight){
    node x{sign,weight};
    return x;
}

void dijkstra(int start,int n){
    for(int i=1;i<=n;i++){
        weight[i]=a[start][i];
    }
    vector<int>path[n+1];
    memset(sign,false,sizeof(sign));
    for(int i=0;i<n;i++){num[i+1]=1;weight[i+1]=inf;}
    weight[start]=0;
    q.push(mp(start,0));
    while(!q.empty()){
        node t=q.top();q.pop();
        if(sign[t.sign])continue;
        sign[t.sign]=true;
        path[t.sign].push_back(t.sign);
        for(int i=1;i<=n;i++){
            if(!sign[i]&&weight[i]==t.weight+a[t.sign][i])num[i]+=num[t.sign]*num2[t.sign][i];
            if(!sign[i]&&weight[i]>t.weight+a[t.sign][i]){
                num[i]=num[t.sign]*num2[t.sign][i];
                weight[i]=t.weight+a[t.sign][i];
                path[i]=path[t.sign];
                q.push(mp(i,weight[i]));
            }
        }
    }//solve 1 to n all the shortest path
    
    //output part
    if(weight[n]==inf){
        cout<<"-1"<<endl<<"0"<<endl<<"-1";}//can't find
    else {
        cout<<weight[n]<<endl<<num[n]<<endl;
        for(int i=0;i<path[n].size();i++){
            cout<<path[n][i]<<" ";//output one path
        }
    }
}

void dijkstra2(int start,int end,int n){
    for(int i=1;i<=n;i++){
        weight[i]=a[start][i];
    }
    vector<int>path[n+1];
    memset(sign,false,sizeof(sign));
    for(int i=0;i<n;i++){num[i+1]=1;weight[i+1]=inf;}
    weight[start]=0;
    q.push(mp(start,0));
    while(!q.empty()){
        node t=q.top();q.pop();
        if(sign[t.sign])continue;
        sign[t.sign]=true;
        path[t.sign].push_back(t.sign);
        for(int i=1;i<=n;i++){
            if(!sign[i]&&weight[i]==t.weight+a[t.sign][i])num[i]+=num[t.sign]*num2[t.sign][i];
            if(!sign[i]&&weight[i]>t.weight+a[t.sign][i]){
                num[i]=num[t.sign]*num2[t.sign][i];
                weight[i]=t.weight+a[t.sign][i];
                path[i]=path[t.sign];
                q.push(mp(i,weight[i]));
            }
        }
        if(sign[end])break;//find the shortest path
    }
    
    //output part
    if(weight[end]==inf){
        cout<<"-1"<<endl<<"0"<<endl<<"-1";
    }//unfind
    else{
    cout<<weight[end]<<endl<<num[end]<<endl;;
    int sum=0;
    for(int i=0;i<path[end].size();i++){
        cout<<path[end][i]<<" ";//output one path
    }
}
}//only find start to end's the shortest path

void solve(){
    int n,m,l,r,k;cin>>n>>m;// n points and m paths
    init();
    for(int i=0;i<m;i++){
        cin>>l>>r>>k;
        if(a[l][r]>k){a[l][r]=k;num2[l][r]=1;a[r][l]=k;num2[r][l]=1;}
        else if(a[l][r]==k){num2[r][l]++;num2[l][r]++;}
    }//undirected graph
    /*for(int i=0;i<m;i++){
        cin>>l>>r>>k;
        if(a[l][r]>k){a[l][r]=k;num2[l][r]=1;}
        else if(a[l][r]==k){num2[l][r]++;}
    }*/   //digraph
    
    dijkstra(1,n);
    //dijkstra2(1,n,n);
}

int main(){
    solve();
}

上一篇:唯一坐标转换问题


下一篇:EOJ_1081_朋友圈