0
点赞
收藏
分享

微信扫一扫

Floyd 判断最小环

小云晓云 2023-02-03 阅读 92


给你一张无向图,定义环为从i出发到达j然后从j返回i并且所有点都只经过一次(最少为3个点),求所有环当中经过路径花费最小的环,花费相同优先选择经过点少的路径。

模板:

#include<algorithm>
#include<iostream>
#include<cstdio>
const int INF=0x3f3f3f3f;
using namespace std;
const int MAXN = 105;

int dis[MAXN][MAXN],g[MAXN][MAXN],fa[MAXN][MAXN],path[MAXN];
int n,m,num,minc;
void Floyd()
{
int i,j,k,p,tmp;
minc=INF;
for(k=1; k<=n; k++)
{
for(i=1; i<k; i++)
for(j=i+1; j<k; j++)
{
tmp=dis[i][j]+g[i][k]+g[k][j];//成环
if(tmp<minc) //找到更优解
{
minc=tmp;
num=0;
p=j;//j作为i-k中间节点
while(p!=i)//逆向寻找前驱结点直到找到最前面的i,i->…->j
{
path[num++]=p;
p=fa[i][p];//fa[i][j]保存的不是k,而是fa[k][j].
}
path[num++]=i;
path[num++]=k;
}
}
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
tmp=dis[i][k]+dis[k][j];
if(dis[i][j]>tmp)
dis[i][j]=tmp,fa[i][j]=fa[k][j];
}
}
}
int main()
{
int i,j,u,v,w;
while(~scanf("%d %d",&n,&m))
{
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
g[i][j]=INF,dis[i][j]=INF,fa[i][j]=i;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
w=min(g[u][v],w); //处理重边
g[u][v]=g[v][u]=dis[u][v]=dis[v][u]=w;
}
Floyd();
if(minc==INF)
printf("No solution\n");
else
{
printf("%d",path[0]);
for(i=1; i<num; i++)
printf(" %d",path[i]);
printf("\n");
}
}
return 0;
}

 

举报

相关推荐

0 条评论