无向图的最小环问题

P6175 无向图的最小环问题

题目简介
给定一张无向图,求图中一个至少包含 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;
}
posted @ 2022-08-01 13:26  何太狼  阅读(266)  评论(0编辑  收藏  举报