D - Association for Control Over Minds Kattis - control (带权并查集)
题目链接:
https://cn.vjudge.net/problem/Kattis-control
题目大意:
当前有很多颜料,每一次搭配有m个,已经混合的颜料不能再分开,问你按照题目给定的顺序能完成几个任务?
具体思路:
对于当前输入的这组数,找到每个的父亲,然后去重;将所有父亲名下的孩子数加起来,如果等于输入的个数,那么当前这组就是合法的,然后再将这些父亲连向最小父亲那个,孩子数也要过度过去。
2 1 2
2 3 4
4 1 2 3 4 5 6
对于这个样例,前两个都是合法的;对于第三个的时候,1名下的孩子有俩,3名下的孩子也有俩,5名下的孩子有一个,6名下的孩子有一个;这样加起来正好有4个,所以是合法的。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 # define LL_inf (1ll<<60) 5 # define inf 0x3f3f3f3f3 6 const int maxn = 5e5+100; 7 int father[maxn]; 8 int num[maxn]; 9 vector<int>sto; 10 int Find(int t) 11 { 12 return t==father[t]?t:father[t]=Find(father[t]); 13 } 14 void emerge(int t1,int t2) 15 { 16 int s1=Find(t1); 17 int s2=Find(t2); 18 if(s1==s2) 19 return ; 20 if(t1>t2) 21 swap(t1,t2); 22 father[t2]=t1; 23 num[t1]+=num[t2]; 24 } 25 int main() 26 { 27 int n,tmp; 28 scanf("%d",&n); 29 for(int i=0; i<maxn; i++)// 注意这里,不是n,应该是500000 30 { 31 father[i]=i; 32 num[i]=1; 33 } 34 int tot; 35 int ans=0; 36 for(int i=1; i<=n; i++) 37 { 38 scanf("%d",&tot); 39 sto.clear(); 40 for(int j=1; j<=tot; j++) 41 { 42 scanf("%d",&tmp); 43 sto.push_back(Find(tmp)); 44 } 45 sort(sto.begin(),sto.end()); 46 sto.erase(unique(sto.begin(),sto.end()),sto.end()); 47 int sz=sto.size(); 48 // cout<<sz<<endl; 49 int tmp=0; 50 for(int j=0; j<sz; j++) 51 { 52 tmp+=num[sto[j]]; 53 } 54 if(tmp==tot) 55 { 56 ans++; 57 for(int j=0; j<sz; j++) 58 { 59 emerge(sto[0],sto[j]); 60 } 61 } 62 } 63 printf("%d\n",ans); 64 return 0; 65 }