1. 程式人生 > >dijkstra最短路

dijkstra最短路

感覺自己太懶了,以後每天更部落格激勵自己吧。



//
時間複雜度O(n*n)的最短路演算法 //首先需要設定一個訪問陣列v[maxn],一個數組d[maxn], memset(v,0,sizeof(v)); for(int i=0;i<n;i++) d[i]=(i==0?0:inf); for(int i=0;i<n;i++) { for(int y=0;y<n;y++) { int x,m=inf; if(!v[y]&&d[y]<=m) m=d[x=y]; v[x]=1; for(int y=0;y<n;y++)
if(d[y]>d[x]+w[x][y]) { d[y]=d[x]+w[x][y]; fa[y]=x; //fa陣列記錄y節點的父節點,如果題目要求輸出最短路路徑,則順著fa陣列輸出就可以了 } //不要求輸出最短路徑時的另一種寫法 //d[y]=min(d[y],d[x]+w[x][y]);只需要更新d[i]就可以了 } } //時間複雜度為O(m*logn的演算法) //利用vector陣列實現圖的儲存 //edges陣列儲存每條邊的資訊,G[i]儲存從i號節點出發, //思想,在原先O(n*n)演算法當中,每次查詢最小的d[i]點,都要for迴圈一遍花去大量的執行步驟
//所以現在用一個優先佇列來儲存每個節點到源點的距離d[i],每次都彈出最小的d[i]省去查詢的時間 //此外借助廣搜的思想,源節點先入隊,然後它的每個子節點如果滿足條件在隊,每個節點都會最多被便利一次 //這對應了第一種樸素演算法中的最外層for迴圈把每個節點都 遍歷一遍 struct Edge{ int from,to,dist; Edge(int u,int v,int d):from(u),to(v),dist(d) {}; }; struct Dijkstra() { int n,m; vector<Edge> edges; vector<int
> G; bool down[maxn]; int d[maxn]; int p[maxn]; void init() { for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int dist) { edges.push_back();//將邊加入邊集 m=edges.size; G[from].push_back(m-1);//由於下標是從零開始的,所以當加入以from開頭的邊時,這條邊的編號為edges的大小-1 } struct heapnode{ int d,u; //定義了每個節點的優先順序比較方法,按照其離源點的距離,小的先輸出 bool oprator <(const heapnode& rhs) const { return d>rhs.d; } }; void dijkstra(int s) { priority_queue<heapnode> Q; for(int i=0;i<n;i++) //初始化每個點到源點的距離為無窮 d[i]=inf; d[0]=0; //源點到自身的距離初始化為0; memset(done,0,sizeof(done)); Q.push((heapnode){0,s}); while(!Q.empty()) { heapnode x=Q.top(); Q.pop(); for(int i=0;i<G[x.u].size;i++) { Edge& e=edges[G[x.u][i]];//G[i]陣列儲存的時i結點的各個邊在e陣列中對應的邊號 if(d[e.to]>d[e.from]+e.dist)//如果到e.to有更短的路,則更新d陣列 { d[e.to]=d[e.from]+e.dist; p[e.to]=G[x.u][i];//儲存到當前節點e.to的最短路徑的上一條邊是誰 Q.push((heapnode){d[e.to],e.to}); } } } } }