最短路模板合集~(Dij+Floyd+Spfa)
阿新 • • 發佈:2019-01-03
自己整理的最短路模板,,對於最短路問題主要就是難在構圖方面~~
~2015.9.5更新//Dijstra O(n^2) //Dijkstra對於有負邊權的最短路徑不支援 void Dijstra() { int i,j; for(i=0; i<n; ++i) { dis[i]=INF; vis[i]=0; } dis[1]=0; int v; for(i=1; i<=n; ++i) { min=INF; for(j=1; j<=n; ++j) { if(!vis[j]&&d[j]<min) //每次找點的過程,首先這個點沒有被發現,然後找一個最小點 { min=d[j]; v=j; } } vis[v]=1; for(j=1; j<=n; ++j) //加進最小點後,再修改從源點沒有被發現的點的最短路徑 { if(!vis[j]&&dis[v]+mp[v][j]<dis[j]) dis[j]=dis[v]+mp[v][j]; } } int ans=-1; for(i=1; i<=n; ++i) if(dis[i]>ans) ans=dis[i]; } int main() { for(int i=0; i<n; ++i) //初始化 類似prim for(int j=0; j<n; ++j) { if(i!=j) mp[i][j]=INF; else mp[i][j]=0; } while(m--) { mp[i][j]=mp[j][i]=~~; } Dijstra(); return 0; } ============================================================= //Dijstra 優先佇列+鄰接表 //優化後複雜度為O(mlogn) struct point { int val,id; point(int id,int val):id(id),val(val) {} bool operator <(const point &x)const { return val>x.val; } }; void dijkstra(int s) { memset(vis,0,sizeof(vis)); for(int i=0; i<n; i++) dis[i]=INF; priority_queue<point> q; q.push(point(s,0)); vis[s]=true; dis[s]=0; while(!q.empty()) { int cur=q.top().id; q.pop(); vis[cur]=true; for(int i=head[cur]; i!=-1; i=e[i].next) { int id=e[i].to; if(!vis[id] && dis[cur]+e[i].val < dis[id]) { dis[id]=dis[cur]+e[i].val; q.push(point(id,dis[id])); } } } } ============================================================= //Floyd O(n^3) void Floyd() { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) mp[i][j]=mp[j][i]=~~; for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) for(int k=0; k<n; ++k) if(mp[j][k]>mp[j][i]+mp[i][k]) mp[j][k]=mp[j][i]+mp[i][k]; } ============================================================= //Spfa 鄰接矩陣 O(kE)E為邊數,k一般為2或3 //可以計算帶負環的迴路 void Spfa() { int i,j; for(int i=0; i<n; ++i) { d[i]=INF; vis[i]=0; } queue<int>q; q.push(start); d[start]=0; vis[start]=1; while(!q.empty()) { int v=q.front(); q.pop(); vis[v]=0; // 這點別忘記 for(i=0; i<n; ++i) { if(d[i]>d[v]+mp[v][i]) { d[i]=d[v]+mp[v][i]; if(!vis[i]) { q.push(i); vis[i]=1; } } } } int ans=-1; for(i=1; i<=n; ++i) if(d[i]>ans) ans=d[i]; } int main() { for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) { if(i!=j) mp[i][j]=INF; else mp[i][j]=0; } while(m--) { mp[i][j]=mp[j][i]=~~; } Spfa(); return 0; } ============================================================= //Spfa 鄰接表(推薦) struct node { int v; int next; int cost; } Edge,e[M]; //Insert //無向圖的spfa的邊要存兩遍 void addEdge() { mp[cnt].v=to; mp[cnt].cost=cost; mp[cnt].next=headlist[from]; headlist[from]=cnt++; mp[cnt].v=to; mp[cnt].cost=cost; mp[cnt].next=headlist[from]; headlist[from]=cnt++; } // void Spfa() { int i,j; for(i=0; i<n; ++i) { d[i]=INF; vis[i]=0; } d[start]=0; vis[start]=1; queue<int>q; q.push(start); while(!q.empty()) { int v==q.front(); q.pop(); vis[v]=0; for(i=headlist[v]; i!=-1; i=mp[i].next) { int b=mp[i].v; if(d[b]>d[v]+mp[i].cost) { d[b]=d[v]+mp[i].cost; if(!vis[b]) { vis[b]=1; q.push(b); } } } } int ans=-1; for(i=1; i<n; ++i) { if(d[u]>ans) ans=d[i]; } } int main() { //for(i=1; i<=n; i++) // headlist[i]=-1; memset(head,-1,sizeof(head)); cnt=0; cin>>from>>to>>cost; // Insert(edge1,head1,u,v,w); // Insert(edge2,head2,v,u,w); } ============================================================= Bellman_ford // 這種演算法比較少用,不多介紹了 //不斷進行鬆弛操作 void bellman_ford() { int i,j,start=1; for(i=1; i<=n; i++) d[i]=INF; d[start]=0; for (i=1; i<n; i++) { //重複進行n-1次收縮 for (j=0; j<m; j++) { //對每條邊進行收縮 if (d[t[j].u]+t[j].w<d[t[j].v]) d[t[j].v]=d[t[j].u]+t[j].w; //分別對每條邊的兩個頂點分別進行收縮 if (d[t[j].v]+t[j].w<d[t[j].u]) d[t[j].u]=d[t[j].v]+t[j].w; } } //簡單說就是不斷進行鬆弛 int ans=-1; for(i=2; i<=n; i++) if(d[i]>ans) ans=d[i]; } int main() { m=0; t[m].u=; t[m].v=; t[m].w=; m++; }