裸题,就是给你一个图,求出最小环。
题目链接:戳我戳我
其实Floyd算法很大部分采用的是dp的思想,利用之前求出来的最短路不断去更新下面的路径值。而求最小环我们可以转换思想:一个环的路径和=这个环的编号最大点到另外两个点的路径和+这两个点的最短路径。因为Floyd是在枚举要经过的点(相当于dp中的分割点的感觉),这样我们就可以在利用Floyd的过程中算出最小环了。
另外需要注意的一点是,这道题是无向图,而Floyd算法用邻接矩阵保存图,尤其注意初始化不要忘记e[a][b]=e[b][a]=w,dis数组也是。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define maxn 105
#define INF 9999999
using namespace std;//无向图
int dis[maxn][maxn];//两个点的最短距离
int edge[maxn][maxn];//两个点之间的边长
int main(void)
{
int n,m;
int a,b,c;
int ans;
while(~scanf("%d%d",&n,&m))
{
memset(dis,INF,sizeof(dis));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
edge[i][j]=dis[i][j]=0;
else
edge[i][j]=edge[j][i]=dis[i][j]=dis[j][i]=INF;
}
}
//
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(dis[a][b]>c)
dis[a][b]=dis[b][a]=c;
if(edge[a][b]>c)
edge[a][b]=edge[b][a]=c;
}
ans=INF;
//cout<<edge[3][1]<<"----"<<endl;
for(int k=1;k<=n;k++)//枚举环中最大的结点,不断扩大环,因为更新距离所以从1开始
{
//ans=INF;
for(int i=1;i<=k-1;i++)
{
for(int j=i+1;j<=k-1;j++)
{
ans=min(ans,edge[i][k]+edge[k][j]+dis[i][j]);
//dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
for(int i=1;i<=n;i++)//依旧要更新距离
{
for(int j=1;j<=n;j++)
{
dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
if(ans<INF)
printf("%d\n",ans);
else
printf("It's impossible.\n");
}
return 0;
}
呼呼