并查集-1

来源:互联网 发布:陈老师spss数据分析 编辑:程序博客网 时间:2024/05/01 09:50

并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。经常采用树林来表示:

1. 查找。查找元素所在的集合即查找根节点。

2. 合并。将两个元素所在的集合合并为一个集合。

3. 合并两个不相交的集合判断两个元素是否属于同一个集合。


我们结合相应的题目来说:

题目描述:
世界上有许多不同的宗教,现在有一个你感兴趣的问题:找出不同的宗教种数,在你的大学中的大学生信仰了多少种不同的宗教。在你的大学有n个学生(0<n<=50 000)。若直接问一个每一个学生的宗教信仰不太适合。此外,许多学生不太愿意说出自己的信仰。有一种方法来避免这个问题,询问m(0=<m<=n(n-1)/2)对学生,询问他们是否信仰同一个宗教(可以询问他们是否都参加同一教堂)。从这个数据,你可能不知道每个人的宗教信仰,但是你可以知道有多少种不同宗教信仰。可以假设,每名学生最多信仰一个宗教。
输入:
输入包含多组测试数据。每组测试数据的开头包含2个整数n和m。接下来m行,每行有两个整数i和j,编号i和j的同学信仰同一宗教。学生的编号从1开始到n。当输入n=0,m=0时,则输入结束。
输出:
每组测试数据的输出只有一行,包含数据的组别(从1开始)和学生最多信仰的宗教数。
样例输入:
10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
2 3
4 5
4 8
5 8
0 0
样例输出:
Case 1: 1
Case 2: 7


分析:

1. 首先我们将每个人的都作为一个节点,初始化时每个节点的父亲节点都是节点本身。

2. 如果要让使不同的宗教信仰是最多的,就假设初始时每个人的宗教信仰不同,那么最大宗教信仰数目sum就是对应的人数,即sum = n

3. 每输入一对宗教信仰相同的人,并且这对人如果当前还属于不同的集合的话,则宗教信仰数-1,即sum--

4. 所有的输入都结束的时候,sum就是所求的结果。

#include<stdio.h> int f[50010], sum;int find(int x){if(f[x] != x)f[x] = find(f[x]);return f[x];}void make(int a, int b){int f1 = find(a);int f2 = find(b);if(f1 != f2){f[f2] = f1;sum --;}}int main(){int n, m ,p = 1, i;while(scanf("%d %d", &n, &m) != EOF){if(n == 0 && m == 0)break;for(i = 1; i <= n; i ++)f[i] = i;sum = n;for(i = 1; i <= m; i ++){int a, b;scanf("%d %d", &a, &b);make(a, b);}printf("Case %d: %d\n", p++, sum);}return 0;}


第一组测试样例:第一行代表f数组的下标,第二行代表f数组下标所对应数组中的值

1234567891012345678910

sum=10

make(1,2)

1234567891011345678910sum = 9
make(1,3)

1234567891011145678910
sum=8

...

make(1,10)

123456789101111111111sum = 1


0 0
原创粉丝点击