1 // 再來一手精髓的Dijkstra 2 // 複雜度O( E*log(V) ) 3 4 #include <cstdio> 5 #include <iostream> 6 #include <vector> 7 #include <queue> 8 9 using namespace std; 10 11 const int max_N = 1000+2; 12 const int max_E = 10000+2; 13 const int INF = 1e9; 14 15 int N,E; 16 int d[max_N]; 17 18 // 來自何方,已經不重要了。 19 // 其實是在鄰接表實現的過程當中,行號即爲來自的頂點 20 struct edge 21 { 22 int to,cost; 23 }; 24 // P.first表明距離,P.second表明頂點編號 25 typedef pair<int,int> P; 26 27 vector<edge> G[max_N]; 28 29 // 這一個算法下來,咱們在數組d中獲得了從s點到其他全部頂點的最短路程 30 void dijkstra(int s) 31 { 32 // 創建最堆,來維護最小距離,能夠下降一層複雜度 33 priority_queue< P,vector<P>,greater<P> > que; 34 35 fill(d,d+N,INF); 36 d[s]=0; 37 que.push(P(0,s)); 38 39 while(!que.empty()) 40 { 41 // 取出一個頂點,看是不是Dijstra算法中,已經肯定的最小頂點 42 P p=que.top(); 43 que.pop(); 44 45 int v=p.second; 46 // 讓咱們來看看這一步 47 // 首先,每次取出堆中的最小元素 48 // 而後去檢索這個堆頂元素的標號所對應的距離 49 // 咦,你會發現堆頂這個距離,居然比取出的最小元素還要小 50 // 驚訝?難道出錯了?沒有,考慮Dijkstra算法的流程,這個頂點確定是以前已經肯定過的最小頂點了,不須要考慮 51 // 以前的實現是多加了一個flag數組來標記,這裏能夠省去這部份內存,直接用這個條件來判斷 52 if(d[v]<p.first) 53 { 54 continue; 55 } 56 57 for(int i=0;i<G[v].size();++i) 58 { 59 edge e=G[v][i]; 60 if(d[e.to] > d[v] + e.cost) 61 { 62 d[e.to]=d[v]+e.cost; 63 // 數組中維護這次被更新的節點便可,其他節點不須要維護 64 que.push(P(d[e.to],e.to)); 65 } 66 } 67 } 68 69 } 70 71 int main() 72 { 73 int a,b,c; 74 scanf("%d %d",&N,&E); 75 for(int i=0;i<E;++i) 76 { 77 scanf("%d %d %d",&a,&b,&c); 78 edge e; 79 e.to=b; 80 e.cost=c; 81 G[a].push_back(e); 82 // 無向圖 83 e.to=a; 84 e.cost=c; 85 G[b].push_back(e); 86 } 87 88 dijkstra(0); 89 90 for(int i=0;i<N;++i) 91 { 92 printf("%d ",d[i]); 93 } 94 95 return 0; 96 } 97 98 /* 99 7 10 100 0 1 2 101 0 2 5 102 1 2 4 103 1 3 6 104 1 4 10 105 2 3 2 106 3 5 1 107 4 5 3 108 4 6 5 109 5 6 9 110 111 112 */