poj 1734 (最小环)
floyd的核心思想就是动态规划从k=0->n来松弛i->j的路径,
因为floyd的外层到k时,i->j的最短路上肯定没有k。所以我们可以先找环,再更新。如果存在的话,那么肯定是i->j 然后j->k->i。这样保证了i->j这条路不经过k。
View Code
1 // File Name: 1734.cpp 2 // Author: Missa 3 // Created Time: 2013/2/7 星期四 16:39:58 4 5 #include<cstdio> 6 #include<cstring> 7 using namespace std; 8 9 const int inf = 100000000; 10 const int maxn = 110; 11 int n,m,num; 12 int dis[maxn][maxn]; 13 int path[maxn][maxn]; 14 int g[maxn][maxn]; 15 int res[maxn]; 16 17 void dfs(int i,int j) 18 { 19 int k=path[i][j]; 20 if(k==0) 21 { 22 res[num++]=j; 23 return ; 24 } 25 dfs(i,k); 26 dfs(k,j); 27 } 28 29 int main() 30 { 31 while(~scanf("%d%d",&n,&m)) 32 { 33 for(int i=1;i<=n;i++) 34 { 35 for(int j=i+1;j<=n;j++) 36 g[i][j]=g[j][i]=dis[i][j]=dis[j][i]=inf; 37 g[i][i]=dis[i][i]=0; 38 } 39 for(int i=0;i<m;i++) 40 { 41 int x,y,z; 42 scanf("%d%d%d",&x,&y,&z); 43 if(z<g[x][y]) 44 { 45 dis[x][y]=dis[y][x]=z; 46 g[x][y]=g[y][x]=z; 47 } 48 } 49 int ans=inf; 50 memset(path,0,sizeof(path)); 51 for(int k=1;k<=n;k++) 52 { 53 for(int i=1;i<k;i++) 54 for(int j=i+1;j<k;j++)//求环 55 if(dis[i][j] +g[i][k]+g[k][j] <ans) 56 { 57 ans=dis[i][j]+g[i][k]+g[k][j]; 58 num=0; 59 res[num++]=i; 60 dfs(i,j); 61 res[num++]=k; 62 } 63 for(int i=1;i<=n;i++) 64 for(int j=1;j<=n;j++) 65 if(dis[i][k]+dis[k][j]<dis[i][j])//松弛 66 { 67 dis[i][j]=dis[i][k]+dis[k][j]; 68 path[i][j]=k; 69 } 70 } 71 if(ans==inf) 72 puts("No solution."); 73 else 74 { 75 printf("%d",res[0]); 76 for(int i=1;i<num;i++) 77 printf(" %d",res[i]); 78 printf("\n"); 79 } 80 } 81 return 0; 82 }