无向图的最小环问题
题目简介
给定一张无向图,求图中一个至少包含 3 个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称为无向图的最小环问题。在本题中,你需要输出最小的环的边权和。若无解,输出 No solution.。
思路
注意题目中的环为至少包括3个点,并且点不重复。
考虑floyd的算法流程,
for(int i=1;i<=n;++i)//外层循环一定是中转点
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
if(g[j][k]>g[j][i]+g[i][k])
g[j][k]=g[j][i]+g[i][k];
最外层枚举的是中转点,当枚举到中转点为i时,我们已经求得了1~i-1号点构成的图的最短路,最重要的时这些点不包括i,这样就满足了点不重复。
我们只需从1~i-1号点中选择两个点x,y,再加上i号点及可构成回路\(x\to y\to i\to x\),记录所有回路的最小值即可。
可以证明若存在最小环,用该方法一定可以找到。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int inf=150000000;
int tmp[N][N],g[N][N];
int n,m;
signed main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
// if(i!=j)
g[i][j]=inf,
tmp[i][j]=inf;
int u,v,w;
for(int i=1;i<=m;++i){
scanf("%d%d%d",&u,&v,&w);
g[u][v]=g[v][u]=w;
tmp[u][v]=tmp[v][u]=w;
}
int ans=inf;
for(int k=1;k<=n;++k){
for(int i=1;i<k;++i)
for(int j=i+1;j<k;++j)ans=min(ans,tmp[i][j]+g[i][k]+g[k][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)tmp[i][j]=min(tmp[i][k]+tmp[k][j],tmp[i][j]);
}
if(ans==inf)printf("No solution.");
else printf("%d",ans);
return 0;
}