URAL1004---Sightseeing trip (Floyed求最小环)

本文介绍了一种求解无向图中最小环路径的方法。通过Floyd算法进行迭代计算,找到从任意一点出发并返回该点的最短路径。文章包含完整的C++实现代码,并附带了解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目来源】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");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值