專題訓練3-圖論 - C - The Suspects(並查集)
阿新 • • 發佈:2022-03-28
題意
2019冠狀病毒病(英語:Coronavirus disease 2019,縮寫:COVID-19 ),是一種由嚴重急性呼吸系統綜合症冠狀病毒2型(縮寫:SARS-CoV-2)引發的傳染病。此病在全球各國大規模爆發並急速擴散,成為人類歷史上致死人數最多的流行病之一。 很顯然,目前最好的辦法就是將所有可能的患者都隔離起來。 現在某高校正在排查可能的患者,這個高校中有多個社團,每個社團經常進行內部交流,一名學生可能會加入多個社團。學校認為一旦某個社團裡出現一名可疑患者,這整個社團的學生都被視為是可能的患者。 現在請你幫忙找到這所學校的所有可能的患者。
(題面漏了一句話:0號學生帶病毒。)
輸入格式
輸入檔案包含多組資料。
對於每組測試資料:
第一行為兩個整數n和m, 其中n是學生的數量, m是社團的數量。0 < n <= 30000,0 <= m <= 500。
接下來m行,每一行有一個整數k,代表社團中學生的數量。之後,有k個整數代表這個社團裡每個學生的編號(在0到n-1之間)。
n = m = 0表示輸入結束,不需要處理。
輸出格式
對於每組測試資料, 輸出可能的患者數目。
樣例
Input | Output |
---|---|
100 4 2 1 2 5 11 13 50 12 14 2 0 1 2 99 2 200 2 1 5 6 5 6 7 8 9 10 1 0 0 0 |
4 1 1 |
思路
並查集模板題。
用0號學生做根節點,用陣列size[]維護樹的節點個數即可,0號學生記錄的size就是答案。
程式碼
#include <iostream> #include <cstring> using namespace std; const int N = 30010; int n, m, k; int p[N], size[N]; int pre, cur; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { while (~scanf("%d%d", &n, &m) && !(!n&&!m)) { memset(p, 0, sizeof p), memset(size, 0, sizeof size); for (int i = 0; i < n; i ++ ) p[i] = i, size[i] = 1; for (int i = 0; i < m; i ++ ) { scanf("%d", &k); if (!k) continue; scanf("%d", &cur); for (int j = 1; j < k; j ++ ) { pre = cur; scanf("%d", &cur); if (j) { if (find(pre) == find(cur)) continue; size[find(pre)] += size[find(cur)]; p[find(cur)] = find(pre); } } } printf("%d\n", size[find(0)]); } return 0; }