題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1529
題意:
Byteazar有N個小豬存錢罐。
每個存錢罐只能用鑰匙開啟或者砸開。
Byteazar已經把每個存錢罐的鑰匙放到了某些存錢罐裡。
Byteazar 現在想買一臺汽車於是要把所有的錢都取出來。
他想盡量少的打破存錢罐取出所有的錢,問最少要打破多少個存錢罐。
題解:
並查集。
如果開啟a的鑰匙放在b中,那麼如果開啟了b,a也能開啟。
所以將a的認爹箭頭指向b。
對於一個集合,只要開啟了這個集合的老大,那麼其他的就都能開啟。
所以答案為集合個數。也就是統計find(i) == i的點的個數。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 1000005 5 6 using namespace std; 7 8 int n; 9 int ans=0; 10 int par[MAX_N]; 11 12 void init_union_find() 13 { 14 for(int i=1;i<=n;i++) 15 { 16 par[i]=i; 17 } 18 } 19 20 int find(int x) 21 { 22 return par[x]==x?x:par[x]=find(par[x]); 23 } 24 25 void unite(int x,int y) 26 { 27 int px=find(x); 28 int py=find(y); 29 if(px==py) return; 30 par[px]=py; 31 } 32 33 bool same(int x,int y) 34 { 35 return find(x)==find(y); 36 } 37 38 void read() 39 { 40 cin>>n; 41 init_union_find(); 42 int a; 43 for(int i=1;i<=n;i++) 44 { 45 cin>>a; 46 unite(i,a); 47 } 48 } 49 50 void solve() 51 { 52 for(int i=1;i<=n;i++) 53 { 54 if(find(i)==i) ans++; 55 } 56 } 57 58 void print() 59 { 60 cout<<ans<<endl; 61 } 62 63 int main() 64 { 65 read(); 66 solve(); 67 print(); 68 }