1. 程式人生 > 實用技巧 >(簡單並查集)The Suspects

(簡單並查集)The Suspects

題目連結

做了大半天終於做出來了,最後AC後發現題目是如此簡單。

算是一道並查集裸題,本質上就是求出集合,然後判斷哪些集合

滿足題意。

剛開始錯誤原因:使用了vector開了二維陣列,但最後發現總是

RE,目前還是百思不得其解。到最後發現題目不需要用二維陣列

儲存輸入的資料,可以直接用判定父節點的陣列來儲存一下資訊

就可以了。

先放錯誤程式碼:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace
std; 6 const int N = 30010; 7 vector<vector<int> >p(520); 8 int fa[N]; 9 bool vis[N]; 10 int find(int x){ 11 if(x != fa[x]) fa[x] = find(fa[x]); 12 return fa[x]; 13 } 14 int main(){ 15 int n, m, k = 0; 16 while(cin >> n >> m ){ 17 memset(vis, 0, sizeof(vis));
18 if(n == 0 && m == 0) break; 19 if(n == 1) 20 cout << 1 << endl; 21 else{ 22 for(int i = 0; i <= k; i ++) 23 p[i].clear(); 24 // for(int i = 1; i <= 5; i ++){ 25 // cout << "-------------------------" << endl;
26 // cout << p[i].size() << endl;; 27 // cout << "-------------------------" << endl; 28 // } 29 int maxn = -0x3f, ans = 0; 30 for(int j = 1; j <= m; j ++){ 31 cin >> k; 32 for(int i = 1; i <= k; i ++){ 33 int num; 34 cin >> num; 35 maxn = max(maxn, num); 36 p[j].push_back(num); 37 } 38 } 39 for(int i = 0; i <= maxn; i ++) fa[i] = i; 40 // for(int i = 0; i <= maxn; i ++){ 41 // cout << "1111111find(" << i << ") = " << find(i) << endl; 42 // } 43 // for(int i = 1; i <= m; i ++){ 44 // for(int j = 0; j < p[i].size(); j ++){ 45 // cout << p[i][j] << ' '; 46 // } 47 // cout << endl; 48 // } 49 50 for(int i = 1; i <= m; i ++) 51 for(int j = 1; j < p[i].size(); j ++){ 52 if(find(p[i][j - 1]) != find(p[i][j])) 53 fa[find(p[i][j - 1])] = find(p[i][j]); 54 } 55 56 // for(int i = 0; i <= maxn; i ++){ 57 // cout << "22222222find(" << i << ") = " << find(i) << endl; 58 // } 59 memset(vis, 0, sizeof(vis)); 60 vis[find(0)] = true; 61 // for(int i = 0; i <= maxn; i ++){ 62 // cout << "3333333find(" << i << ") = " << find(i) << endl; 63 // } 64 for(int i = 0; i <= maxn; i ++) 65 if(vis[find(i)]){ 66 //cout << "i = " << i << " find(" << i << ") = " << find(i) << endl; 67 ans ++; 68 } 69 70 cout << ans << endl; 71 } 72 } 73 74 75 return 0; 76 }

AC程式碼如下:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 30010;
 7 int fa[N], arr[N];
 8 bool vis[N];
 9 int find(int x){
10     if(x != fa[x]) fa[x] = find(fa[x]);
11     return fa[x];
12 }
13 int main(){
14     int n, m, k = 0;
15     while(cin >> n >> m ){
16         memset(vis, 0, sizeof(vis));
17         if(n == 0 && m == 0) break;
18         if(n == 1){
19             cout << 1 << endl;
20             continue;
21         }
22             
23         int maxn = -0x3f, ans = 0;
24         for(int i = 0; i <= N; i ++) fa[i] = i;
25         for(int i = 0; i < m; i ++){
26             cin >> k;
27             for(int j = 0; j < k; j ++){
28                 cin >> arr[j];
29                 maxn = max(maxn, arr[j]);//記錄一下最大值,後面可以避免不必要的遍歷
30                 if(j >= 1)
31                     if(find(arr[j - 1]) != find(arr[j]))
32                         fa[find(arr[j - 1])] = find(arr[j]);
33             }
34         }
35         
36 
37         memset(vis, 0, sizeof(vis));
38         vis[find(0)] = true;
39         for(int i = 0; i <= maxn; i ++)
40             if(vis[find(i)])
41                 ans ++;
42                     
43         cout << ans << endl;
44 
45     }
46 
47     return 0;
48 }