並查集之路徑壓縮
阿新 • • 發佈:2021-01-24
技術標籤:機試技巧
路徑壓縮函式:
const int maxn = 10010;
int father[maxn];
int findfather(int x) {
int temp = x;
while (x != father[x])
x = father[x];
while (temp != father[temp]) {
int temp2 = temp;
temp = father[temp];
father[temp2] = x;
}
return x;
}
好朋友(演算法題解)
有一個叫做“數碼世界”奇異空間,在數碼世界裡生活著許許多多的數碼寶貝,其中有些數碼寶貝之間可能是好朋友,並且數碼寶貝世界有兩條不成文的規定:
第一,數碼寶貝A和數碼寶貝B是好朋友等價於數碼寶貝B與數碼寶貝A是好朋友
第二,如果數碼寶貝A和數碼寶貝C是好朋友,而數碼寶貝B和數碼寶貝C也是好朋友,那麼A和B也是好朋友
現在給出這些數碼寶貝中所有好朋友的資訊問:可以把這些數碼寶貝分成多少組,滿足每組中的任意兩個數碼寶貝都是好朋友,而且任意兩組之間的數碼寶貝都不是好朋友
輸入的第一行有兩個正整數n(n <= 100)和m(m <= 100),分別表示數碼寶貝的個數和好朋友的組數,其中數碼寶貝編號為1~n。
輸出一個整數,表示這些數碼寶貝可以分成的組數
7 5
1 22 3
3 1
1 4
5 6
3
#include <iostream> #include<cstdio> #include<algorithm> #include<string.h> #include<string> #include<stack> #include<cmath> #include<map> #include<queue> using namespace std; #pragma warning(disable:4996) const int maxn = 10010; int father[maxn]; bool isroot[maxn]; int findfather(int x) { int temp = x; while (x != father[x]) x = father[x]; while (temp != father[temp]) {//路徑壓縮 int temp2 = temp; temp = father[temp]; father[temp2] = x; } return x; } void Union(int a, int b) {//合併兩集合 int faA = findfather(a); int faB = findfather(b); if (faA != faB)father[faA] = faB; } void init(int n) { for (int i = 1; i <= n; i++) { father[i] = i; isroot[i] = false; } } int main() { int n, m, a, b; scanf("%d%d", &n, &m); init(n); for (int i = 0; i < m; i++) { scanf("%d%d", &a, &b); Union(a, b); } for (int i = 1; i <= n; i++) isroot[findfather(i)] = true; int ans = 0; for (int i = 1; i <= n; i++) ans += isroot[i]; printf("%d\n", ans); return 0; }