(F. MST Unification)最小生成树

题目链接:http://codeforces.com/contest/1108/problem/F

题目大意:给你n个点和m条边,然后让你进行一些操作使得这个图的最小生成树唯一,每次的操作是给某一条边加1,然后让你求出最小的操作数。

具体思路: 最小生成树不唯一的话,指的是至少有两条边权相等的边,这两条边中的任意一条都能构成一个最小生成树的边。那么如何避免这种局面出现?

如果两个边权相等的边在最小生成树上(可以互相替换),也就是说这两条边最这个最小生成树上的作用是可以相互替代的,那么我们在加边的时候首先考虑处理边权相等的边,这里处理的边还应该再筛选一下,我们需要处理的那些边是指的相互替代的边(如果不能相互替代,就说明这条边在最小生成树上是其他边不能替代的)。

具体过程就是先把所有边按照边权进行排序,然后再去处理矛盾的边就可以了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define inf 0x3f3f3f3f
 5 const int maxn = 2e5+100;
 6 struct node
 7 {
 8     int fr;
 9     int to;
10     int cost;
11 } q[maxn];
12 bool cmp(node t1,node t2)
13 {
14     return t1.cost<t2.cost;
15 }
16 int father[maxn];
17 int Find(int t)
18 {
19     return t==father[t]?t:father[t]=Find(father[t]);
20 }
21 int main()
22 {
23     int n,m,t1,t2,t3;
24     scanf("%d %d",&n,&m);
25     for(int i=1; i<=n; i++)
26     {
27         father[i]=i;
28     }
29     for(int i=1; i<=m;i++)
30     {
31         scanf("%d %d %d",&t1,&t2,&t3);
32         q[i].fr=t1;
33         q[i].to=t2;
34         q[i].cost=t3;
35     }
36     sort(q+1,q+m+1,cmp);
37     int ans=0;
38     for(int i=1; i<=m; )
39     {
40         int j=i;
41         int num=0;
42         while(j<=m&&q[j].cost==q[i].cost)
43             j++;
44         for(int k=i; k<j; k++)
45         {
46             int t1=Find(q[k].fr);
47             int t2=Find(q[k].to);
48             if(t1!=t2)
49             {
50                 num++;
51             }
52         }
53         for(int k=i; k<j; k++)
54         {
55             int t1=Find(q[k].fr);
56             int t2=Find(q[k].to);
57             if(t1!=t2)
58             {
59                 father[t1]=t2;
60                 num--;
61             }
62         }
63         i=j;
64         ans+=num;
65     }
66     printf("%d\n",ans);
67     return 0;
68 }

 

posted @ 2019-01-25 17:54  Let_Life_Stop  阅读(312)  评论(0编辑  收藏  举报