Floyd —Warshall(最短路及其他用法详解)
一、多元最短路求法
多元都求出來了,單源的肯定也能求。
思想是動態(tài)規(guī)劃的思想:從任意節(jié)點(diǎn)A到任意節(jié)點(diǎn)B的最短路徑不外乎2種可能,1是直接從A到B,2是從A經(jīng)過若干個節(jié)點(diǎn)X到B。所以,我們假設(shè)Dis(AB)為節(jié)點(diǎn)A到節(jié)點(diǎn)B的最短路徑的距離,對于每一個節(jié)點(diǎn)X,我們易寫出狀態(tài)轉(zhuǎn)移方程Dis(AB) =min(Dis(AX) + Dis(XB) ,Dis(AB))這樣一來,當(dāng)我們遍歷完所有節(jié)點(diǎn)X,Dis(AB)中記錄的便是A到B的最短路徑的距離。
這里一定要把K寫到外邊,需要先更新K前面的點(diǎn)在更新K后的點(diǎn)才有意義。
結(jié)合代碼 并參照上圖所示 我們來模擬執(zhí)行下 這樣才能加深理解:
第一關(guān)鍵步驟:當(dāng)k執(zhí)行到x,i=v,j=u時,計算出v到u的最短路徑要通過x,此時v、u聯(lián)通了。
第二關(guān)鍵步驟:當(dāng)k執(zhí)行到u,i=v,j=y,此時計算出v到y(tǒng)的最短路徑的最短路徑為v到u,再到y(tǒng)(此時v到u的最短路徑上一步我們已經(jīng)計算過來,直接利用上步結(jié)果)。
第三關(guān)鍵步驟:當(dāng)k執(zhí)行到y(tǒng)時,i=v,j=w,此時計算出最短路徑為v到y(tǒng)(此時v到y(tǒng)的最短路徑長在第二步我們已經(jīng)計算出來了),再從y到w。
依次掃描每一點(diǎn)(k),并以該點(diǎn)作為中介點(diǎn),計算出通過k點(diǎn)的其他任意兩點(diǎn)(i,j)的最短距離,這就是floyd算法的精髓!同時也解釋了為什么k點(diǎn)這個中介點(diǎn)要放在最外層循環(huán)的原因.
完整代碼:
#include<iostream> #include<stack> using namespace std; #define MAX 1000 int Graph[MAX][MAX]; int Dis[MAX][MAX]; #define infinite 1000 int path[MAX][MAX];void floyd(int N) {int i,j,k;for(k=0;k<N;k++){for(i=0;i<N;i++){for(j=0;j<N;j++){if(Dis[i][k]+Dis[k][j]<Dis[i][j]){Dis[i][j]=Dis[i][k]+Dis[k][j];path[i][j]=k;}}}}}void print_path(int N) {int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if((i!=j) &&Dis[i][j]!=infinite){cout<<i+1<<"----"<<j+1<<" distance:"<<Dis[i][j]<<endl;cout<<"path:"<<endl;int k=j;stack <int> ph;do{k=path[i][k];ph.push(k);}while(k!=i);cout<<ph.top()+1;ph.pop();while(!ph.empty()){cout<<"->"<<ph.top()+1;ph.pop();}cout<<"->"<<j+1<<endl;}}} }void main() {int N,i,j;cin>>N;for(i=0;i<N;i++){for(j=0;j<N;j++){int g;cin>>g;Graph[i][j]=g;Dis[i][j]=g;}} //初始化路徑for(i=0;i<N;i++){for(j=0;j<N;j++){path[i][j]=i;}}floyd(N);print_path(N);system("pause"); }二、連通性
講Dis[i][j]不連聯(lián)通時設(shè)置為0,聯(lián)通時設(shè)置為1.
則可得狀態(tài)轉(zhuǎn)移方程
dis[i][j]=dp[i][j]||(dp[i][k]&&dp[k][j]);
跟上面代碼除了狀態(tài)轉(zhuǎn)移方程之外還有初始化不同,這個都初始化為0;
其余都一樣。要么ij直接連通,要么ij通過K聯(lián)通。
三、求無向圖中可以刪除一些邊,使得任意兩點(diǎn)的最短路不改變,求這些邊能刪除的最大的條數(shù)。(最小生成樹問題)
首先先在輸入邊的時候?qū)⒅剡吶サ?#xff0c;保留最小的。
然后進(jìn)行佛洛依德。
如果原來兩點(diǎn)的最短距離大于經(jīng)過第三個點(diǎn)的最短距離的話,那么我們就將這兩點(diǎn)的最短距離
替換成經(jīng)過第三條邊的最短距離,當(dāng)循環(huán)節(jié)結(jié)束后通過對比兩點(diǎn)之間的距離變化,即可知哪些邊將被刪去。但是~~~當(dāng)兩點(diǎn)之間本來沒有邊的情況下,我們肯定是經(jīng)過第三個點(diǎn)所到達(dá)的。那么就沒有替換原來的邊,這種情況的話,就直接continue;
四、無向圖最小環(huán)
若用dis[i][j]表示ij之間的最小值,則由i j 加線外一點(diǎn)k的環(huán)值為dis[i][j]+length[i][k]+length[k][j];
枚舉中間點(diǎn)k,在用其更新最短路前,先找最小環(huán),令1<=i<j<k,即k點(diǎn)必定不在i,j的最短路上,則這個環(huán)中至少有三個點(diǎn),可得狀態(tài)轉(zhuǎn)移方程 ans=min(ans,dis[i][j]+length[i][k]+length[k][j]);
五、傳遞閉包問題
鄰接矩陣是顯示兩點(diǎn)的直接關(guān)系,如a直接能到b,就為1。而傳遞閉包顯示的是傳遞關(guān)系,如a不能直接到c,卻可以通過a到b到d再到c,因此a到c為1。
另外矩陣A進(jìn)行自乘即A{2}得到的矩陣中,為1的值表示走最多兩步可以到達(dá)。A{3}矩陣中為1的值表示,最多走三步可以到達(dá)。
簡單來說,就是有向圖確定先后順序。
總結(jié)
以上是生活随笔為你收集整理的Floyd —Warshall(最短路及其他用法详解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 任意进制转化 函数 模板(一)
- 下一篇: USACO Training Secti