題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=3296
題意:
農夫約翰的N(2 <= N <= 10,000)頭奶牛,編號為1...N。
一共會流利地使用M(1<= M <=30,000)種語言,編號從1...M。
第i頭,會說K_i(1 <= K_i <= M)種語言,即L_i1, L_i2,..., L_{iK_i} (1 <= L_ij <= M)。
FJ的奶牛不太聰明,所以K_i的總和至多為100,000。
兩頭牛,不能直接交流,除非它們都會講某一門語言。然而,沒有共同語言的奶牛們,可以讓其它的牛給他們當翻譯。換言之,牛A和B可以談話,當且僅當存在一個序列奶牛T_1,T_2,...,T_k,A和T_1都會說某一種語言,T_1和T_2也都會說某一種語言...並且T_k和B會說某一種語言。
農夫約翰希望他的奶牛更加團結,所以他希望任意兩頭牛之間可以交流。他可以買書教他的奶牛任何語言。作為一個相當節儉的農民,FJ想要購買最少的書籍,讓所有他的奶牛互相可以說話。
幫助他確定:他必須購買的書籍的最低數量。
題解:
並查集。
將所有有共同語言的牛合併。
因為當前所有的集合兩兩之間都沒有共同語言,所以每買一本書,只能將其中兩個集合合併。
所以:最後答案 = 集合個數 - 1
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 10005 6 #define MAX_M 30005 7 8 using namespace std; 9 10 int n,m; 11 int ans=0; 12 int par[MAX_N]; 13 int lang[MAX_M]; 14 15 void init_union_find() 16 { 17 for(int i=0;i<n;i++) 18 { 19 par[i]=i; 20 } 21 } 22 23 int find(int x) 24 { 25 return par[x]==x?x:par[x]=find(par[x]); 26 } 27 28 void unite(int x,int y) 29 { 30 int px=find(x); 31 int py=find(y); 32 if(px==py) return; 33 par[px]=py; 34 } 35 36 bool same(int x,int y) 37 { 38 return find(x)==find(y); 39 } 40 41 void read() 42 { 43 cin>>n>>m; 44 init_union_find(); 45 memset(lang,-1,sizeof(lang)); 46 int k,l; 47 for(int i=0;i<n;i++) 48 { 49 cin>>k; 50 for(int j=0;j<k;j++) 51 { 52 cin>>l; 53 if(lang[l]!=-1) unite(i,lang[l]); 54 else lang[l]=i; 55 } 56 } 57 } 58 59 void solve() 60 { 61 for(int i=0;i<n;i++) 62 { 63 if(find(i)==i) ans++; 64 } 65 } 66 67 void print() 68 { 69 cout<<ans-1<<endl; 70 } 71 72 int main() 73 { 74 read(); 75 solve(); 76 print(); 77 }