1. 程式人生 > 其它 >並查集之路徑壓縮

並查集之路徑壓縮

技術標籤:機試技巧

路徑壓縮函式:

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;
}

好朋友(演算法題解)

Description

有一個叫做“數碼世界”奇異空間,在數碼世界裡生活著許許多多的數碼寶貝,其中有些數碼寶貝之間可能是好朋友,並且數碼寶貝世界有兩條不成文的規定:

第一,數碼寶貝A和數碼寶貝B是好朋友等價於數碼寶貝B與數碼寶貝A是好朋友
第二,如果數碼寶貝A和數碼寶貝C是好朋友,而數碼寶貝B和數碼寶貝C也是好朋友,那麼A和B也是好朋友

現在給出這些數碼寶貝中所有好朋友的資訊問:可以把這些數碼寶貝分成多少組,滿足每組中的任意兩個數碼寶貝都是好朋友,而且任意兩組之間的數碼寶貝都不是好朋友

在這裡插入圖片描述

Input

輸入的第一行有兩個正整數n(n <= 100)和m(m <= 100),分別表示數碼寶貝的個數和好朋友的組數,其中數碼寶貝編號為1~n。

Output

輸出一個整數,表示這些數碼寶貝可以分成的組數

Sample Input

7 5
1 2

2 3
3 1
1 4
5 6

Sample Output

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;
}