Floyd求最小环
原理:不讲。
模板如下。
1 #include<cstdio> 2 #include<cstring> 3 #define find_min(a,b) a<b?a:b 4 5 const int N=109; 6 const int INF=0x7ffffff; 7 int f[N][N],dis[N][N],pre[N][N],path[N],n,m,num; 8 9 int main() 10 { 11 scanf("%d%d",&n,&m); 12 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) 15 f[i][j]=dis[i][j]=INF,pre[i][j]=i; 16 17 while(m--) 18 { 19 int a,b,c; 20 scanf("%d%d%d",&a,&b,&c); 21 f[a][b]=f[b][a]=dis[a][b]=dis[b][a]=find_min(f[a][b],c); 22 } 23 24 int min=INF; 25 for(int k=1;k<=n;k++)//最短路径外一点将最短路首尾链接,那么就得到一个最小环,枚举中间点 26 { 27 for(int i=1;i<k;i++) 28 for(int j=i+1;j<k;j++) 29 { 30 //求最小环不能用两点间最短路松弛,因为(i,k)之间的最短路,(k,j)之间的最短路可能有重合的部分 31 //所以f[][]其实是不更新的,这里和单纯的floyd最短路不一样 32 //dis[i][j]保存的是 i 到 j 的最短路权值和,(i->j) 33 int tmp=dis[i][j]+f[i][k]+f[k][j];//这里k分别和i还有 j在f[][]中直接相连 34 if(tmp<min) 35 { 36 min=tmp;num=0; 37 int p=j; 38 while(p!=i)//回溯 39 { 40 path[num++]=p; 41 p=pre[i][p];//pre[i][j]表示i->j最短路径上j前面的一个点 42 } 43 path[num++]=i; path[num++]=k; 44 } 45 } 46 47 for(int i=1;i<=n;i++) 48 for(int j=1;j<=n;j++) 49 if(dis[i][j]>dis[i][k]+dis[k][j]) 50 { 51 dis[i][j]=dis[i][k]+dis[k][j];//dis[][]保存两点间最短距离 52 pre[i][j]=pre[k][j]; 53 } 54 55 } 56 if(min==INF)puts("No solution."); 57 else 58 { 59 printf("%d",path[0]); 60 for(int i=1;i<num;i++) 61 printf(" %d",path[i]); 62 puts(""); 63 } 64 return 0; 65 }
例题:POJ 1734 Sightseeing trip
HDU 1599 find the mincost route