find the mincost route HDU - 1599

http://acm.hdu.edu.cn/showproblem.php?pid=1599

floyd求最小环问题 有向图的话 跑一遍模板然后n^2扫一遍就好 但是无向图不能这样无脑搞 比如三阶完全图 边权都相等 那就不存在松弛了 明明有环但是判不出 想通过记录最小次小值来搞又会出现重点问题 比如题目第二个样例 dis[1][3]=2 dis[3][2]=1=>dis[1][2]=3 这样本来没环给判出环了

最外层循环到k的话 说明[1,k-1]都已经发挥了松弛作用 也就是说当前任意两点之间被松弛的最短距离 都是由[1,k-1]确定的 与[k,n]无关 这样可以枚举[k,n]来通过e[i][k]+e[k][j]+dis[i][j](i,j<k)来找出最小环 但是[k+1,n]目前可以确定的环之后可定会被算上 只用k这个点扫一遍就完事了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1000000000;
const int maxn=1e2+10;

ll e[maxn][maxn],dis[maxn][maxn];
int n,m;

ll floyd()
{
    ll res;
    int i,j,k;
    res=N;
    for(k=1;k<=n;k++){
        for(i=1;i<=k-1;i++){
            for(j=i+1;j<=k-1;j++){
                res=min(res,dis[i][j]+e[i][k]+e[k][j]);
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    return res;
}

int main()
{
    ll ans,w;
    int i,j,u,v;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                if(i==j) e[i][j]=0;
                else e[i][j]=N;
            }
        }
        while(m--){
            scanf("%d%d%lld",&u,&v,&w);
            e[u][v]=min(e[u][v],w);
            e[v][u]=min(e[v][u],w);
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                dis[i][j]=e[i][j];
            }
        }
        ans=floyd();
        if(ans==N) printf("It's impossible.\n");
        else printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/84852180