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