floyd改進版求最小環
阿新 • • 發佈:2018-12-22
最小環改進演算法的證明
設一個環中的最大結點為k(編號最大), 與他相連的兩個點為i, j, 這個環的最短長度為g[i][k]+g[k][j]+i到j的路徑中所有結點編號都小於k的最短路徑長度。
根據floyd的原理, 在最外層迴圈做了k-1次之後, dist[i][j]則代表了i到j的路徑中所有結點編號都小於k的最短路徑綜上所述,該演算法一定能找到圖中最小環。
先上模板:
#include<bits/stdc++.h> using namespace std; int dis[111][111],e[111][111]; int n,m; int main() { int a,b,c; while(cin>>n>>m){ memset(dis,0x3f,sizeof(dis)); memset(e,0x3f,sizeof(e)); for(int i=0;i<m;i++){ cin>>a>>b>>c; e[a][b]=c; e[b][a]=c; dis[a][b]=c; dis[b][a]=c; } int ans=0x3f3f3f3f; for(int k=1;k<=n;k++){ for(int i=1;i<=k-1;i++) { for(int j=i+1;j<=k-1;j++){ ans=min(ans,dis[i][j]+e[i][k]+e[k][j]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++){ dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } } } if(ans==0x3f3f3f3f) cout<<"沒有最小環"<<endl; else{ cout<<"最小環長度為:"<<ans<<endl; } } }
直接上程式碼:
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; const int maxn = 105; const int inf = 1e8; int n,m; int dis[maxn][maxn],mp[maxn][maxn];//dis表示最短路徑,mp表示兩點間直線距離(題中給出的值存入mp) void floyd(){ int MinCost = inf; for(int k=1;k<=n;k++){ for(int i=1;i<k;i++) for(int j=i+1;j<k;j++) MinCost = min(MinCost,dis[i][j]+mp[i][k]+mp[k][j]);//更新k點之前列舉ij求經過ijk的最小環 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); //更新k點 } if(MinCost==inf)puts("It's impossible."); else printf("%d\n",MinCost); } int main() { while(scanf("%d%d",&n,&m) == 2){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) mp[i][j]=dis[i][j]=inf; for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=min(w,mp[u][v]); } floyd(); } return 0; }