(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 }