优化算法,floyd的同时求出最小环。
#include<stdio.h>
long g[500][500],dis[500][500];
int main()
{
FILE *in,*out;
in=fopen ("circle.in","r");
out=fopen ("circle.out","w");
long n,m,i,j,a,b,c,ans=214000000,k;
fscanf (in,"%ld %ld",&n,&m);
for (i=0;i<=n;i++)
for (j=0;j<=n;j++)
g[i][j]=dis[i][j]=21400000;
for (i=0;i<m;i++)
{
fscanf (in,"%ld %ld %ld",&a,&b,&c);
g[b][a]=g[a][b]=c;
dis[a][b]=dis[b][a]=c;
}
for (k=1;k<=n;k++)
{
for (i=1;i<k;i++)
for (j=i+1;j<k;j++)
ans=ans>dis[i][j]+g[i][k]+g[k][j]?dis[i][j]+g[i][k]+g[k][j]:ans;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
dis[i][j]=dis[i][j]>dis[i][k]+dis[k][j]?dis[i][k]+dis[k][j]:dis[i][j];
}
fprintf (out,"%ld/n",ans);
}
对 于每一个k,都有i,j<k,故可以保证每一个环都被枚举到了,并且求环时dis[i,j]尚未被更新,所以不会出现dis[i,j]与 g[i,j]表示的是同一路径的问题。由于同一个环可以有许多个i,j,k,因而对于更新后的dis[i,j]在接下来的循环中可以被利用。
求一个图G中的最小环路朴素算法是求E遍dijkstra:每次找到一条边,删去,再求这两点间的最短路,若可以求出,则这条最短路与原边构成一个环,时间复杂度是O(en2)。