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\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2019-01-25 16:07  shuai_hui  阅读(1010)  评论(0编辑  收藏  举报