/*无向图的最小环问题:
无向图的最小环的求法不可能和有向图的求法一样, 因为在有向图中i 到j 和 j 到i 算是一个环,但在无向图中不是一个环,
如果直接用flody算法将会出错, 有向图的环可以为2个顶点,而无向图的环至少要三个顶点; 所以为了求无向图的最小环, 我们采用的原理是: 枚举最大环中的连接点,更新环的权重;
比普通Floyd多出来的部分,主要利用到的原理是当处理到k时,所有以1 到k - 1为中间结点的最短路径都已经确定,则这时候的环为(i到j(1 < i, j <= k - 1)的最短路径) + 边(i, k) + 边(k, j)遍历所有的i, j找到上述式子的最小值即位k下的最小代价环.
还有一个细节就是要注意初始化的inf。0x7fffffff。是2^31-1.即int的最大范围。这样相加会溢出。
调用计算机上的calc。*/
#include <stdio.h>
#include <cstring>
const int maxn=101;
int g[maxn][maxn];
int dis[maxn][maxn];
int ans[maxn];
int pre[maxn][maxn];
const int inf=9999999;
int minnum(int a,int b)
{
return a<b?a:b;
}
int main()
{
int n,m,u,v,w;
while(scanf("%d%d",&n,&m)==2)
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
dis[i][j]=g[i][j]=inf,pre[i][j]=i;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
g[u][v]=g[v][u]=dis[u][v]=dis[v][u]=minnum(w,g[u][v]);
}
int t,temp;
int min=inf;
for(int k=1; k<=n; k++)
{
for(int i=1; i<=k-1; i++)
{
for(int j=i+1; j<=k-1; j++)
{
if(dis[i][j]+g[i][k]+g[k][j]<min)
{
min=dis[i][j]+g[i][k]+g[k][j];
t=0;
temp=j;
while(i!=temp)
{
ans[t++]=temp;
temp=pre[i][temp];
}
ans[t++]=i;
ans[t++]=k;
}
}
}
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(dis[i][k]+dis[k][j]<dis[i][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
pre[i][j]=pre[k][j];
}
}
}
if(min==inf) printf("No solution.\n");
else
{
for(int i=0; i<t-1; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[t-1]);
}
}
return 0;
}

本文介绍了一种求解无向图中最小环的具体算法。该算法基于Floyd算法进行改进,通过枚举最大环中的连接点来更新环的权重,并详细解释了实现过程中的关键步骤和技术细节。

1059

被折叠的 条评论
为什么被折叠?



