您的位置:首页 > 其它

URAL - 1004 Sightseeing Trip(最小环)

2017-08-02 09:58 323 查看

Sightseeing Trip

题目链接:Sightseeing Trip

题意:给你一个无向有环图,有n个点,m条边(可能有重边),问图中的最小环是多少,打印出最小环

思路:

一种方法是:对于每一个(u,v),去掉(u,v)这条边,然后最短路跑一遍计算出u到v的最短距离s,s+dis[u][v]就是环的长度,遍历找出最小环即可

另一种方法是:在用Floyd()松弛之前,对于当前的每一个k,都可以看成存在以k为起点和终点的环(k点为环中最大的点),并且环中的所有边都没有被k松弛过。

那么对于每一个k点,只需要先寻找k的最小环再松弛即可

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int inf=1e8;//注意inf不能过大,否则会爆int
const int maxn=105;
int dis[maxn][maxn],mp[maxn][maxn],path[maxn],pre[maxn][maxn];//dis表示松弛的图,mp表示原图,pre记录前面的点
int n,m,minx,tot;

void Floyd()
{
minx=inf;
for(int k=1; k<=n; ++k)
{
for(int i=1; i<k; ++i)
for(int j=i+1; j<k; ++j)
{
if(dis[i][j]+mp[i][k]+mp[k][j]<minx)
{
minx=dis[i][j]+mp[i][k]+mp[k][j];
tot=0;
int tmp=j;
path[tot++]=j;
while(tmp!=i)
{
tmp=pre[i][tmp];
path[tot++]=tmp;
}
path[tot++]=k;
}
}
for(int i=1; i<=n; ++i)
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的写法
}
}
}

void init()
{
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
{
dis[i][j]=mp[i][j]=inf;
pre[i][j]=i;
}
}

int main()
{
while(scanf("%d",&n)&&(n+1))
{
init();
scanf("%d",&m);
int u,v,w;
for(int i=1; i<=m; ++i)
{
scanf("%d%d%d",&u,&v,&w);
if(w<mp[u][v])
mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=w;
}
Floyd();
if(minx==inf)
printf("No solution.\n"
d1d2
);
else
{
for(int i=0; i<tot-1; ++i)
printf("%d ",path[i]);
printf("%d\n",path[tot-1]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: