【题目来源】:https://cn.vjudge.net/problem/URAL-1004
【题意】
给出n个点,m条双向边,赋权,问,在整个无向图中,最小环的路径。
什么是最小环呢,也就是从i点经过某些点重新回到i点的最小距离。
【思路】
最小环记录路径模板题。
给出两篇不错的讲解:求最小环讲解,以及最小环。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=1e9;
int w[110][110];
int dis[110][110];
int pre[110][110];
int path[110];
int num,minn,n,m;
void floyed()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<k;i++)
{
for(int j=i+1;j<k;j++)
{
int ans=dis[i][j]+w[j][k]+w[k][i];//最小环的总长度:i-->x1..x2..x3..xm-->j-->k-->i。
if(ans<minn)
{
minn=ans;
num=1;
int p=j;
while(p!=i)
{
path[num++]=p;
p=pre[i][p];
}
path[num++]=i;
path[num++]=k;
}
}
}
for(int i=1;i<=n;i++)//求i-->x1..x2..x3..xm-->j的最短路(不包括点k)
{
for(int j=1;j<=n;j++)
{
if(dis[i][j]>dis[i][k]+dis[k][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
pre[i][j]=pre[k][j];//记录更新过后最短路的上一个点,比如这里pre[i][j]最初存的是i,pre[k][j]存的是k。
}
}
}
}
}
int main()
{
while(~scanf("%d",&n))
{
if(n==-1) break;
scanf("%d",&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
w[i][j]=w[j][i]=INF;
dis[i][j]=dis[j][i]=INF;
pre[i][j]=i;
}
}
for(int i=1;i<=m;i++)
{
int u,v,value;
scanf("%d%d%d",&u,&v,&value);
w[u][v]=w[v][u]=dis[u][v]=dis[v][u]=min(w[u][v],value);
}
minn=INF;
floyed();
if(minn==INF)
{
printf("No solution.\n");
continue;
}
for(int i=1;i<num;i++)
{
if(i!=1)printf(" ");
printf("%d",path[i]);
}
printf("\n");
}
}