/* Dijkstra 算法求单源最短路径 将所有结点分为两个集合 S D ,S为未访问的结点集合,D为已访问的集合 每次从集合D中找到一条到达集合S中结点的最短路径,将该点加入到D集合,并更新加入该点后的最短路径 */ #include<iostream> #include<cstring> #include<queue> using namespace std; const int MAX=1E9; const int Size=720; class Dist{ //存放找到的当前最短路径 public: int index; //结点下标 int length; //路径长度 int pre; //当前结点前驱下标 friend const bool operator < (const Dist &a,const Dist &b) { return a.length>b.length;//小的优先级高,用于优先队列 } }; class Graph{ public: int numv; //结点数 int *mark; //标记已访问结点,未访问为0 int * *ma; //邻接矩阵 Graph(int n) { numv=n; ma=(int * *)new int [n]; for(int i=0;i<n;i++)ma[i]=new int[n]; mark=new int [n]; } }; void Dijkstra(Graph &G,int s,Dist* &D) //s为源点 { using std::priority_queue; D=new Dist[G.numv]; for(int i=0;i<G.numv;i++) //Dist初始化 { G.mark[i]=0; D[i].index=i; D[i].length=MAX; //Dist存放长度为极大值,若算法结束后仍为极大值认为未找到可达路径 D[i].pre=s; } D[s].length=0; priority_queue<Dist> H; //优先队列,存放最短路径 H.push(D[s]); for(int i=0;i<G.numv;i++) { bool f=false; Dist d; while(!H.empty()) { d=H.top(); H.pop(); if(G.mark[d.index]==0) //寻找未访问结点 { f=true; break; } } if(!f)break; //未找到可访问结点退出 int v=d.index; //v找到的当前结点 G.mark[v]=1; //标记v为已访问 for(int i=0;i<G.numv;i++) { if(G.ma[v][i]>0) //访问v的边,i为目标点 { if(D[i].length>(D[v].length+G.ma[v][i])) //若经过v的某条边,使得s到i的距离比Dist中存放的最短路更短 { D[i].length=D[v].length+G.ma[v][i]; //更新Dist[i](s到i的最短路) D[i].pre=v; //改变到i的最短路前驱为v H.push(D[i]); //将新的最短路放入优先队列 } } } } } int main() { int n;cout <<"d"<<endl; int a,b,c,e; Dist *d; Graph g(100); while(cin>>n) { g.numv=n+1; for(int i=0;i<=n;i++)g.mark[i]=0; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) g.ma[i][j]=0; while(cin>>a>>b) { if(a==-1&&b==-1)break; cin >> c; g.ma[a][b]=c; } cin>>e; Dijkstra(g,e,d); for(int i=1;i<n+1;i++) cout << d[i].index << " " <<d[i].length <<" "<<d[i].pre<<endl; } return 0; } /* 3 1 2 8 1 3 3 3 2 3 -1 -1 1 5 1 4 30 1 2 10 1 5 100 2 3 50 3 5 10 4 5 60 4 2 10 4 3 20 -1 -1 1 6 1 3 15 2 1 10 2 4 2 2 6 30 4 2 20 4 5 15 5 2 4 6 3 4 6 5 10 6 1 10 -1 -1 2 */