• CF F. MST Unification (最小生成树避圈法)


    题意

    给一个无向加权联通图,没有重边和环。在这个图中可能存在多个最小生成树(MST),你可以进行以下操作:选择某条边使其权值加一,使得MST权值不变且唯一。求最少的操作次数。

    分系:首先我们先要知道为什么会出现多个最小生成树的情况? 因为有些边的权值是相同的 , 所以在构造最小生成树的时候 ,我们是可以选择不同的边 , 构造出不同的最小生成树;

    如果我们要是生成的最小生成树是唯一的 , 那我们每一次的加边十都只能是一种选择

    也就是说,在构造过程的某一次抉择中,如果有多条边,他们的权值均最小,且合法(不会构成环,可以加入MST),而且冲突【二者只能选其一,即选择其中一条后,另一条再加进去就会构成环】,那么我们只选择一条加入MST,剩下的冲突边,都权值加一,那么他们就不能再被选到MST里面了。


    为什么必须强调是冲突边?因为如果不冲突,我们可以先选择一条边权最小的(为w)的边e1加入,下次再选择时,边权最小还是为w,但是现在是边e2了,此时e2由于不会构成环,还是可以加入到MST中。所以实际上它们两个是在同一个方案里的,不够成多种选择。
    很明显,上面的构造过程是采用了 kruskal算法(即避圈法),我们只需要在构造过程中,统计冲突边的数量,累加起来即可。
    ---------------------

    原文:https://blog.csdn.net/Floraqiu/article/details/86630053

    #include<bits/stdc++.h>
    using namespace std ;
    const int maxn = 2e5+10;
    int n,m,fa[maxn];
    struct no{
    int u,v,w;
    }e[maxn];
    bool cmp(no a , no b)
    {
        return a.w<b.w;
    }
    void init(){
    for(int i=1 ; i<=n ; i++)
        fa[i]=i;
    }
    
    int Find(int x)
    {
        return x==fa[x] ? x:fa[x]=Find(fa[x]);
    }
    void Merge(int x, int y)
    {
        int fx = Find(x), fy = Find(y);
        if(fx != fy)
            fa[x] = fy;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(int i=0 ; i<m ; i++)
            scanf("%d%d%d",&e[i].u , &e[i].v , &e[i].w);
            sort(e , e+m , cmp);
            int ans=0;
            for(int i=0 ; i<m ; )
            {
                int num=0;
                int j=i;
                while(e[i].w ==e[j].w) ///找到权值相同的尾部坐标
                j++;
    
                for(int k=i ; k<j ; k++) ///i到j都是边权最小而且都是相同的边
                {
                    int fx = Find(e[k].u) , fy=Find(e[k].v);
                    if(fx!=fy)///统计可以选择的合法边的数量
                    num++;
                }
                ///注意,我们还得判断合法边里的冲突边 ,才是我们想要的答案
                for(int k=i ; k<j ; k++)
                {
                    int fx=Find(e[k].u) , fy=Find(e[k].v);
                    if(fx!=fy)///从合法边中减去非冲突边(即可以被选入到同一个方案里,不互相冲突的边)
                    Merge(fx,fy) , num--;
                }
                i=j;
                ans+=num;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C#设计模式之策略模式
    c#设计模式之单例模式
    关于分布式事务的实现梳理
    sql事务的使用及其技巧整理
    关于web系统整体优化提速总结
    .net导出excle无需任何插件,直接通过一个tablehtml实现
    ajax+ashx:实现文件的批量导出
    angularjs学习第九天笔记(指令作用域【隔离作用域】研究)
    angularjs学习第八天笔记(指令作用域研究)
    angularjs小练习(分别通过ng-repeat和ng-option动态生成select下拉框)
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10320158.html
Copyright © 2020-2023  润新知