用dijkstra获得全部最短路径

来源:互联网 发布:mini metro mac下载 编辑:程序博客网 时间:2024/05/20 16:32

无向图,但是很容易改成有向图

#include <cstdio>#include <cstring>#include <iostream>#include <vector>#include <map>#include <set>#include <queue>#define MAX 1000#define rep(i,n) for(i=0;i<n;++i)using namespace std;//节点(名称 权重)struct node{    int rank;    int weight;    node(int r,int w):rank(r),weight(w){}};//距离 以及节点名称struct dis{    int rank;    int dist;//当前已知最短距离    dis(){}    dis(int h,int w):rank(h),dist(w){}    bool operator > (const dis& p)const{        return dist>p.dist;    }};int n,m;int d[MAX];char Index[MAX];bool visited[MAX];vector<int> path[MAX];vector<node> adj[MAX];void findPath(int start){    int i,size,rank,j,size2;    size=(int)adj[start].size();    rep(i,size){        if(d[adj[start][i].rank]==d[start]+adj[start][i].weight){            rank=adj[start][i].rank;            if(path[rank].empty()||(*(path[rank].end()-1)!=rank)){                path[rank]=path[start];                path[rank].push_back(rank);                findPath(rank);            }else{                path[rank].push_back(-1);                size2=(int)path[start].size();                rep(j,size2){                    path[rank].push_back(path[start][j]);                }                path[rank].push_back(rank);                //findPath(rank);            }        }    }}inline void dijkstra(int start){    dis now;    int size,i,rank;    memset(visited,0, sizeof(visited));    memset(d,-1, sizeof(d));    visited[start]=true;    d[start]=0;    priority_queue<dis,vector<dis>,greater<dis> > pq;    pq.push(dis(start,0));    while(!pq.empty()){        now=pq.top();pq.pop();        size=(int)adj[now.rank].size();        rep(i,size){            if(!visited[adj[now.rank][i].rank]){                rank=adj[now.rank][i].rank;                visited[rank]=true;                if(d[rank]!=-1&&d[rank]<=d[now.rank]+adj[now.rank][i].weight)                    continue;                d[rank]=d[now.rank]+adj[now.rank][i].weight;                pq.push(dis(rank,d[rank]));            }        }    }    rep(i,n)        path[i].clear();    path[start].push_back(start);    findPath(start);}void output(int start){    int i,j,size;    rep(i,n)if(i!=start){            printf("%c->%c:\n",Index[start],Index[i]);            size=(int)path[i].size();            rep(j,size){                if(path[i][j]!=-1)                    printf("%c",Index[path[i][j]]);                else{                    printf("\n");                    continue;                }                if(j==size-1)                    printf("\n");                else if(path[i][j+1]!=-1)                    printf("->");            }            printf("length:%d\n\n",d[i]);        }}inline void input(){//输入新图:第一行输入点的个数和边的个数 接下来每一行一条边 两个端点 长度    char u,v;    int i,w,k=0,p1,p2;    set<char> allNode;    map<char,int> map;    scanf("%d%d",&n,&m);    rep(i,m){        cin>>u>>v>>w;        if(u!=v){            if(!allNode.count(u)){                allNode.insert(u);                map[u]=k;                Index[k]=u;                p1=k;                ++k;            }else p1=map[u];            if(!allNode.count(v)){                allNode.insert(v);                map[v]=k;                Index[k]=v;                p2=k;                ++k;            }else p2=map[v];            adj[p1].push_back(node(p2,w));            adj[p2].push_back(node(p1,w));        }    }}inline void solve(){    int i;    rep(i,n){        dijkstra(i);        output(i);    }}int main(){    int op,i;    again:    printf("运行原图(1)\n输入新图(2)\n推出(0)\n");    scanf("%d",&op);    switch(op){        //输出实验拓扑图所有最短路径        case 1:{            n=8;            m=11;            //A B C D E F G H            //0 1 2 3 4 5 6 7            Index[0]='A';            Index[1]='B';            Index[2]='C';            Index[3]='D';            Index[4]='E';            Index[5]='F';            Index[6]='G';            Index[7]='H';            //A B 1            adj[0].push_back(node(1,1));            adj[1].push_back(node(0,1));            //A E 4            adj[0].push_back(node(4,4));            adj[4].push_back(node(0,4));            //A H 3            adj[0].push_back(node(7,3));            adj[7].push_back(node(0,3));            //B G 5            adj[1].push_back(node(6,5));            adj[6].push_back(node(1,5));            //B D 2            adj[1].push_back(node(3,2));            adj[3].push_back(node(1,2));            //D G 2            adj[3].push_back(node(6,2));            adj[6].push_back(node(3,2));            //E C 2            adj[2].push_back(node(4,2));            adj[4].push_back(node(2,2));            //E F 1            adj[4].push_back(node(5,1));            adj[5].push_back(node(4,1));            //F C 3            adj[2].push_back(node(5,3));            adj[5].push_back(node(2,3));            //C G 4            adj[2].push_back(node(6,4));            adj[6].push_back(node(2,4));            //H D 1            adj[7].push_back(node(3,1));            adj[3].push_back(node(7,1));            solve();        }            break;        case 2:{            input();            solve();        }            break;        case 0:            return 0;        default:            printf("输入有误,请重新输入\n");            break;    }    rep(i,n){        adj[i].clear();    }    goto again;}
原创粉丝点击