其他分享
首页 > 其他分享> > 2020-11-28

2020-11-28

作者:互联网

并查集+路径压缩(POJ 2524)

题目链接: http://poj.org/problem?id=2524.
并查集
x与y是同一门派的,y与z是同一门派的,那么x与z也是同一门派的。
给出N个人(1~n),m对关系(并不是所以人都)。并查集可以构建出n个点中有几个连通图,判断任意两个点是否在们一个连通图中。
fa[i]=s;
i=s 表示i是一个根节点(可以理解为一个门派的掌门)
i!=s 表示i的上一级是s,s不一定是掌门。
初始化:将自己的上层节点(即父节点)设置为自己)

查找x的掌门:
判断x的上一级 f[x]是等于x,若不等于,就去找X的上一级的上一级(即f[x]的上一级),直到找到为止。
代码:

int query(int x){
	if(x==f[x]) return x;
		query(f[x])
}

v,w两个点时同一个门派的,将他们合并。
代码:

v=query(v);
w=query(w);
f[w]=v;

Sample Input

10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10

10 4
2 3
4 5
4 8
5 8
0 0

Sample Output

Case 1: 1
Case 2: 7

题意:学校有n个同学,每个同学有且只有一个信仰,给出m对有同一信仰的同学,问存在多少种不同的信仰?

package 并查集;
import java.util.Scanner;
public class Main {
	static int n,m,fa[];
	public static void main(String[] args) {
		Scanner sr=new Scanner(System.in);
		int c=1;
		while((n=sr.nextInt())!=0&&(m=sr.nextInt())!=0) {
			fa=new int[n+1];
			for(int i=1;i<=n;i++) {
				fa[i]=i;
			}
			for(int i=0;i<m;i++) {
				int x=query(sr.nextInt());
				int y=query(sr.nextInt());
				fa[x]=y;
			}
			int ans=0;
			for(int i=1;i<=n;i++) {
				if(i==query(i)) ans++;
			}
			System.out.println("Case "+c+": "+ans);
			c++;
		}
	}
	static int query(int x) {
		if(fa[x]==x) return x;
		return fa[x]=query(fa[x]);
	}
}

标签:11,门派,int,sr,查集,28,fa,2020,query
来源: https://blog.csdn.net/weixin_44019271/article/details/110278189