Codeforces Round #535 (Div. 3) F

F. MST Unification

题目传送门

  题意

 给你n个顶点,m条边;保证没有重边,其中存在多个MST(最小生成树),

 你可以修改一些边的权值,让其中有且仅有一个最小生成树,求最少操作的边数。

  思路:

 最小生成树算法的加工,我们从kruskal算法入手,kruskal就是先对边排序,

然后遍历边不断加入一些合格边来完善最小生成树

那么在这个过程中,如果边的权值一样的话,就会产生多种MST,但是这里

不能仅仅只是累计相同权值的边数,因为与合格边相同权值的边可能可以选择

多条。

所以我们可以将所有符合的边累加起来,然后减去(n-1)就是与合格边冲突的边

,也就是答案了

#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n,m;
struct node
{
    int u,v,w;
    bool operator <(const node &p) const{
      return w<p.w;
    }
}edge[N];
int fa[N];

int Find(int x)
{
    if(x==fa[x]) return x;
    else return fa[x]=Find(fa[x]);
}
int main()
{
   while(~scanf("%d %d",&n,&m))
   {
      for(int i=0;i<m;i++)
        scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
      for(int i=1;i<=n;i++) fa[i]=i;
       sort(edge,edge+m);
       int ans=0;
       int L=0;
       for(int i=0;i<m;i++)
       {
           int u=edge[i].u,v=edge[i].v;
           u=Find(u),v=Find(v);
           if(u!=v) ans++;
           if(i+1<m && edge[i].w!=edge[i+1].w)
           {
               for(int j=L;j<=i;j++)
               {
                   int u=edge[j].u,v=edge[j].v;
                   u=Find(u),v=Find(v);
                   if(u!=v) fa[u]=v;
               }
               L=i+1;
           }
       }
       printf("%d\n",ans-(n-1));
   }
}
View Code

 

posted @ 2019-01-27 21:50  better46  阅读(115)  评论(0编辑  收藏  举报