有 n 個學生(編號 0~n-1),已知 m 對關係 (a, b) 表示 a 和 b 試卷相同。求與 0 號學生試卷相同的其他學生人數(不含 0 號)。多組測試數據,EOF 結束。n ≤ 100000, m ≤ 10000。
並查集完美支持「動態連通性」查詢。將每對關係 Union(a, b),最後遍歷 1~n-1,統計 Find(i) == Find(0) 的個數。
MakeSet(n):初始化 fa[i] = i。Find(x):路徑壓縮 return fa[x] == x ? x : fa[x] = Find(fa[x])。Union(x, y):fx = Find(x), fy = Find(y); if (fx != fy) fa[fy] = fx;(可加按秩優化)。int fa[100010];
int Find(int x) {
return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
void Union(int x, int y) {
x = Find(x); y = Find(y);
if (x != y) fa[y] = x;
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 0; i < n; i++) fa[i] = i;
for (int i = 0; i < m; i++) {
int a, b; scanf("%d%d", &a, &b);
Union(a, b);
}
int cnt = 0;
for (int i = 1; i < n; i++)
if (Find(i) == Find(0)) cnt++;
printf("%d\n", cnt);
}
return 0;
}
經典並查集入門題。路徑壓縮(+按秩合併)使操作幾乎為常數時間。注意數組大小開到 100010,輸入以 EOF 結束,輸出不含 0 號本身。