poj1734Sightseeing trip——无向图求最小环

题目:http://poj.org/problem?id=1734

无向图求最小环,用floyd;

在每个k点更新f[i][j]之前,以k点作为直接连到i,j组成一个环的点,这样找一下最小环;

注意必须存直接相连的边,在找环时k点连到i,j的值不能是最短路。

调了一个小时发现把z打成y了......

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,f[105][105],pre[105][105],ans,path[105],inf=1e9,top;
int sid[105][105];//真的有必要存直接相连的边 
int main()
{
    scanf("%d%d",&n,&m);
    memset(f,-1,sizeof f);
    memset(sid,-1,sizeof sid);
    ans=inf;
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(f[x][y]==-1)//
        {
            f[x][y]=f[y][x]=z;
            pre[x][y]=x;pre[y][x]=y;
            sid[x][y]=z;sid[y][x]=z;
        }
        else
            f[x][y]=f[y][x]=sid[x][y]=sid[y][x]=min(f[x][y],z);
    }
    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<k;i++)//找环 
            for(int j=i+1;j<k;j++)
            {
//                if(k==5)printf("i=%d j=%d  ans=%d %d\n",i,j,ans,f[i][j]+sid[i][k]+sid[k][j]);
                if(f[i][j]!=-1&&sid[i][k]!=-1&&sid[k][j]!=-1&&ans>f[i][j]+sid[i][k]+sid[k][j])
                {
                    ans=f[i][j]+sid[i][k]+sid[k][j];
//                    printf("sid[%d][%d]=%d\n",k,j,sid[k][j]);
//                    printf("ans=%d\n",ans);
//                    printf("!f[%d][%d]=%d f[%d][%d]=%d\n",i,k,f[i][k],k,j,f[k][j]);
                    top=0;
                    int t=j;
                    while(t!=i)
                    {
                        path[++top]=t;
                        t=pre[i][t];
                    }
                    path[++top]=i;
                    path[++top]=k;//前提为k为单出一点 
                }
            }
        for(int i=1;i<=n;i++)//
            for(int j=1;j<=n;j++)//
                if(f[i][k]!=-1&&f[k][j]!=-1&&(f[i][j]>f[i][k]+f[k][j]||f[i][j]==-1))//
                {
//                    printf("f[%d][%d]=%d f[%d][%d]=%d\n",i,k,f[i][k],k,j,f[k][j]);
                    f[i][j]=f[i][k]+f[k][j];
                    pre[i][j]=pre[k][j];
                }
                
    }
    if(ans==inf)printf("No solution.");
    else
    {
        for(int i=1;i<=top;i++)
            printf("%d ",path[i]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Zinn/p/8711922.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值