题目大意:给出N个点(N<100),M条边(M<10000),求无向图中的最小环
考察点:floyd
思路分析:
一个环中的最大结点为k(编号最大),与他相连的两个点为i,j,这个环的最短长度为g[i][k]+g[k][j]+i到j的路径中,所有结点编号都小于k的最短路径长度
根据floyd的原理,在最外层循环做了k-1次之后,dist[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径。
综上所述,该算法一定能找到图中最小环(这个算法还可用于判断负权环)。
#include<stdio.h>
#define min(x,y) (x)<(y)? (x):(y)
int a[150][150],f[150][150];
int main()
{
int n,m,i,j,k,x,y,z,ans;
scanf("%d",&n);
while (n!=-1)
{
scanf("%d",&m);
for (i=0;i<=110;i++)
for (j=0;j<=110;j++)
{
a[i][j]=10000000;f[i][j]=a[i][j];
}
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
a[x][y]=min(a[x][y],z);f[x][y]=a[x][y];
a[y][x]=a[x][y];f[y][x]=a[x][y];
}
ans=10000000;
for (k=1;k<=n;k++)
{
for (i=1;i<=n;i++)
for (j=i+1;j<=n;j++)
ans=min(ans,f[i][j]+a[i][k]+a[k][j]);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
if (ans==10000000) printf("-1\n");
else printf("%d\n",ans);
scanf("%d",&n);
}
return 0;
}