zoukankan      html  css  js  c++  java
  • URAL 1416 Confidential --最小生成树与次小生成树

    题意:求一幅无向图的最小生成树与最小生成树,不存在输出-1

    解法:用Kruskal求最小生成树,标记用过的边。求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就是次小的生成树。可以证明:最小生成树与次小生成树之间仅有一条边不同。不过这样复杂度有点高,可达O(m^2).

    求次小生成树有O(mlogm+n^2)的算法,详见

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define Mod 1000000007
    using namespace std;
    #define N 507
    
    struct Edge
    {
        int s,t,w;
    }edge[N*N];
    
    int fa[N],use[N],n,m,minedge;  //minedge:最小生成树的边数
    
    void init()
    {
        for(int i=1;i<=n;i++)
            fa[i] = i;
    }
    
    int cmp(Edge ka,Edge kb)
    {
        return ka.w < kb.w;
    }
    
    int findset(int x)
    {
        if(x != fa[x])
            fa[x] = findset(fa[x]);
        return fa[x];
    }
    
    int Kruskal_MinTree()
    {
        int u,v;
        init();
        int i,flag,cnt;
        minedge = 0;
        flag = cnt = 0;
        int tmp = 0;
        for(i=0;i<m;i++)
        {
            u = edge[i].s;
            v = edge[i].t;
            int fx = findset(u);
            int fy = findset(v);
            if(fx != fy)
            {
                use[minedge++] = i;
                tmp += edge[i].w;
                fa[fx] = fy;
                cnt++;
            }
            if(cnt == n-1)
            {
                flag = 1;   //找到最小生成树
                break;
            }
        }
        if(flag)
            return tmp;
        return -1;   //不存在最小生成树,返回-1
    }
    
    int Sec_MinTree()
    {
        int i,j,mini,tmp;
        int cnt,flag,u,v;
        mini = Mod;
        for(i=0;i<minedge;i++)   //枚举最小生成树中的每条边,将其去除
        {
            init();
            flag = cnt = tmp = 0;
            for(j=0;j<m;j++)
            {
                if(j != use[i])  //去除边
                {
                    u = edge[j].s;
                    v = edge[j].t;
                    int fx = findset(u);
                    int fy = findset(v);
                    if(fx != fy)
                    {
                        cnt++;
                        tmp += edge[j].w;
                        fa[fx] = fy;
                    }
                    if(cnt == n-1)
                    {
                        flag = 1;
                        break;
                    }
                }
            }
            if(flag && tmp < mini)
                mini = tmp;
        }
        if(mini == Mod)
            mini = -1;
        return mini;
    }
    
    int main()
    {
        int i,j;
        int u,v,w;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&u,&v,&w);
                edge[i].s = u;
                edge[i].t = v;
                edge[i].w = w;
            }
            sort(edge,edge+m,cmp);
            int flag = Kruskal_MinTree();
            int mini = Sec_MinTree();
            printf("Cost: %d
    ",flag);
            printf("Cost: %d
    ",mini);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    BZOJ1033:[ZJOI2008]杀蚂蚁antbuster(模拟)
    BZOJ4001:[TJOI2015]概率论(卡特兰数,概率期望)
    BZOJ1820:[JSOI2010]Express Service 快递服务(DP)
    BZOJ4066:简单题(K-D Tree)
    2110. [NOIP2015普及]金币
    73. 找最佳通路
    cogs 7. 通信线路
    codevs 3295 落单的数
    151. [USACO Dec07] 建造路径
    必备算法之二叉树的相关操作
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3643800.html
Copyright © 2011-2022 走看看