• Floyd求最小环!(转载,非原创) 附加习题(原创。)HDU-1599


     

    //Floyd 的 改进写法可以解决最小环问题,时间复杂度依然是 O(n^3),储存结构也是邻接矩阵
    
    int mincircle = infinity;
    Dist = Graph;
    
    for(int k=0;k<nVertex;++k){
        //新增部分:
        for(int i=0;i<k;++i)
            for(int j=0;j<i;++j)
                 mincircle = min(mincircle,Dist[i][j]+Graph[j][k]+Graph[k][i]);
        //通常的 floyd 部分:
        for(int i=0;i<nVertex;++i)
            for(int j=0;j<i;++j){
                int temp = Dist[i][k] + Disk[k][j];
                if(temp < Dist[i][j])
                     Dist[i][j] = Dist[j][i] = temp;
             }
    }

     


    以上为网上流传的Floyd求最小环的主代码。我们发现,最下面两重循环就是Floyd原来的代码,新增的就是上面那个判环部分。一开始,我不明白,为什么要把新增的放在前面,两者的顺序能不能调换?现在的理解是这样的:在第k层循环,我们要找的是最大结点为k的环,而此时Dist数组存放的是k-1层循环结束时的经过k-1结点的最短路径,也就是说以上求出的最短路是不经过k点的,这就刚好符合我们的要求。为什么呢?假设环中结点i,j是与k直接相连,如果先求出经过k的最短路,那么会有这样一种情况,即:ij的最短路经过k。这样的话就形成不了环,显然是错误的。当时还有一个问题,就是为什么要多开一个Dist数组呢,一个Graph不是足够了吗?其实好好想想,出现的问题和前面是一个道理。如果只开Graph,那么它里面的值就会不断改变,也会存在路径覆盖的情况,导致形成不了环或不是最小环。举个例子:假设现在进行第k层循环,i,j为枚举出来与k直接相连的边。由于此时Graph是动态的,原来根本不存在ik的一条边,现在可能经过其它结点形成了“边”,但它未必是与k直接相连的边。以上两个问题花了我半天时间来弄懂,由于网上也没有找到关于这些问题的(可能我比较笨吧),所以要写这些东西,但又写得挺乱……

     

    题目大意:中文题,求三个地点形成的最小环。

     

    解决方法:之上的floyd最小环算法;

     

    AC代码:

     

    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define INF 0x3f3f3f3f
    int n,m;
    int map_[1000][1000];
    int dis[1000][1000];
    int main()
    {
        while (cin>>n>>m)
        {
            memset(map_,INF,sizeof(map_));
            for (int i=1; i<=m; i++)
            {
                int a,b,c;
                cin>>a>>b>>c;
                //cout<<a<<b<<c<<endl;
                map_[a][b]=map_[b][a]=min(c,map_[a][b]);
               // cout<<map_[a][b]<<map_[b][a]<<endl;
            }
            for (int i=1; i<=n; i++)
            {
                for (int j=1; j<=n; j++)
                {
                   // cout<<map_[i][j]<<" ";
                    dis[i][j]=map_[i][j];
                }//cout<<endl;;
            }
            int ans=INF;
            for (int k=1; k<=n; k++)
            {
                for (int i=1; i<=n; i++)
                {
                    for(int j=1; j<=n; j++)
                    {
                        if (i!=j&&j!=k&&i!=k&&map_[i][k]!=INF&&map_[k][j]!=INF&&dis[i][j]!=INF)
                        {
                            ans=min(ans,dis[i][j]+map_[j][k]+map_[k][i]);
                            //cout<<ans<<endl;
                        }
                    }
                }
                for (int i=1; i<=n; i++)
                {
                    for (int j=1; j<=n; j++)
                    {
                        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                    }
                }
            }
            if (ans==INF) cout<<"It's impossible."<<endl;
            else
                cout<<ans<<endl;
        }
        return 0;
    }

     

     

     

  • 相关阅读:
    BZOJ 2956: 模积和
    BZOJ 1113: [Poi2008]海报PLA
    停课刷题总结-给自己一点鼓励吧
    BZOJ 2751: [HAOI2012]容易题(easy)
    Vijos 1100 加分二叉树
    BZOJ 1756: Vijos1083 小白逛公园
    BZOJ 1709: [Usaco2007 Oct]Super Paintball超级弹珠
    BZOJ 1652: [Usaco2006 Feb]Treats for the Cows
    BZOJ 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚
    BZOJ 1631: [Usaco2007 Feb]Cow Party
  • 原文地址:https://www.cnblogs.com/SunQi-lvbu/p/7076358.html
Copyright © 2020-2023  润新知