并查集之路径压缩

路径压缩函数:

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

猜你喜欢

转载自blog.csdn.net/ur_ytii/article/details/113061041