圖論:Floyd-多源最短路、無向圖最小環

在最短路問題中,若是咱們面對的是稠密圖(十分稠密的那種,好比說全鏈接圖),計算多源最短路的時候,Floyd算法才能充分發揮它的優點,不折不扣戰勝SPFA和Dijkstra算法

在別的最短路問題中都不推薦使用這個算法數組

咱們以一道單源最短路題目介紹一下在輸入數據爲邊表的狀況下的Floyd使用狀況,若是直接給了鄰接矩陣的話,直接無腦求就能夠了函數

在這裏,咱們把Floyd算法的功能補全,實現了一個打印最短路徑的函數並加入了求無向圖的最小環的功能(通過至少兩個定點,權值和最小)spa

看定義:code

int n,m,s,mina=INF; int d[maxn][maxn],mp[maxn][maxn],p[maxn][maxn];

n個點m條邊和源點s,最小環初始化爲INFblog

而後d是最短路的答案數組,mp是初始地圖數組,p是記錄兩個點之間的銜接點k,用來打印路徑遞歸

而後是初始化:string

void init() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d[i][j]=mp[i][j]=INF; for(int i=1;i<=n;i++) d[i][i]=mp[i][i]=0; }

這裏注意,若是給的是邊表,必需要這麼作,若是給的是矩陣,能夠直接忽略這個函數了it

而後是Floyd算法:io

void floyd() { for(int k=1;k<=n;k++) { for(int i=1;i<k;i++) for(int j=i+1;j<k;j++) mina=min(d[i][j]+mp[j][k]+mp[k][i],mina); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(d[i][k]<INF&&d[k][j]<INF) d[i][j]=min(d[i][j],d[i][k]+d[k][j]),p[i][j]=k; } }

若是單純忽略mina的求解過程,這就是一個裸的,Floyd

咱們再看一下路徑是怎麼打印的,其實很顯然:

void output(int i,int j) { if(i==j) return; if(p[i][j]==0) printf("%d ",j); else{output(i,p[i][j]);output(p[i][j],j);} }

遞歸的思路仍是很明顯的

咱們給出完整的實現:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;  5 const int maxn=1005;  6 const int maxm=2005;  7 const int INF=0x7fffffff;  8 int n,m,s,mina=INF;  9 int d[maxn][maxn],mp[maxn][maxn],p[maxn][maxn]; 10 void init() 11 { 12     for(int i=1;i<=n;i++) 13     for(int j=1;j<=n;j++) 14         d[i][j]=mp[i][j]=INF; 15     for(int i=1;i<=n;i++) d[i][i]=mp[i][i]=0; 16 } 17 void floyd() 18 { 19     for(int k=1;k<=n;k++) 20  { 21         for(int i=1;i<k;i++) 22         for(int j=i+1;j<k;j++) 23             mina=min(d[i][j]+mp[j][k]+mp[k][i],mina); 24              
25         for(int i=1;i<=n;i++) 26         for(int j=1;j<=n;j++) 27         if(d[i][k]<INF&&d[k][j]<INF) 28             d[i][j]=min(d[i][j],d[i][k]+d[k][j]),p[i][j]=k; 29  } 30 } 31 void output(int i,int j) 32 { 33     if(i==j) return; 34     if(p[i][j]==0) printf("%d ",j); 35     else{output(i,p[i][j]);output(p[i][j],j);} 36 } 37 int main() 38 { 39     scanf("%d%d%d",&n,&m,&s); 40     int x,y,z; 41  init(); 42     for(int i=1;i<=m;i++) {scanf("%d%d%d",&x,&y,&z);mp[x][y]=d[x][y]=min(z,d[x][y]);} 43  floyd(); 44     for(int i=1;i<=n;i++) printf("%d ",d[s][i]); 45     return 0; 46 }

請注意,請注意,請注意

在不保證沒有重邊的狀況下,必定要有

mp[x][y]=d[x][y]=min(z,d[x][y]);

不然涼涼

相關文章
相關標籤/搜索