并查集
题目
现在有107个用户,编号为1- 107,现在已知有m对关系,每一对关系给你两个数x和y,代表编号为x的用户和编号为y的用户是在一个圈子中,例如:A和B在一个圈子中,B和C在一个圈子中,那么A,B,C就在一个圈子中。现在想知道最多的一个圈子内有多少个用户。
输入输出
第一行输入一个整数T,接下来有T组测试数据。
对于每一组测试数据:第一行输入1个整数n,代表有n对关系。
接下来n行,每一行输入两个数x和y,代表编号为x和编号为y的用户在同一个圈子里。
1 ≤ T ≤ 10
1 ≤ n ≤ 105
1 ≤ x, y ≤ 107
对于每组数据,输出一个答案代表一个圈子内的最多人数
输入例子
2
4
1 2
3 4
5 6
1 6
4
1 2
3 4
5 6
7 8
输出例子
4
2
代码
import java.util.*;
import java.lang.Math;
public class Main{
public static void main(String[] argv){
int T,n;
Scanner sc = new Scanner(System.in);
T = sc.nextInt();
while(T-- > 0){
n = sc.nextInt();
int[][] r = new int[n][2];
int num = 0;
for(int i = 0; i < n; i++){ //存储元素,并获得元素最大值
r[i][0] = sc.nextInt();
r[i][1] = sc.nextInt();
num = Math.max(num,r[i][0]);
num = Math.max(num,r[i][1]);
}
System.out.println(new Main().neighber(r,num));
}
}
public int neighber(int[][] r,int num){
int[] set = new int[num + 1]; //存储父节点索引
int[] count = new int[num +1]; //存储每个节点集合元素个数
for(int i = 1; i <= num; i++){
set[i] = -1;//初始化,set为-1表示不存在该元素,count[i]表示当前以i为根的树包含的元素个数
count[i] = 1;
}
for(int i = 0; i < r.length; i++){ //出现过的元素让父节点值等于本身
set[r[i][0]] = r[i][0];
set[r[i][1]] = r[i][1];
}
for(int i = 0; i < r.length; i++){
union(r[i][0],r[i][1],set,count); //合并两个节点
}
int maxNum = 1;
for(int i = 1; i <= num; i++){ //统计最大值,等于本身表示是根节点
if(set[i] == -1)
continue;
else if(set[i] == i){
maxNum = Math.max(count[i],maxNum);
}
}
return maxNum;
}
public int findRoot(int x, int[] set){ //查找根节点,不等于本身则迭代
while(set[x] != x){
x = set[x];
}
return x;
}
public void union(int x ,int y, int[] set,int[] count){
int xRoot = findRoot(x,set);
int yRoot = findRoot(y,set);
if(xRoot != yRoot){ //根节点不相同时合并
/* int j = x;
while(set[j] != j){ //优化树结构,每次合并都把迭代的父节点合并到根节点,降低树的高度为2
int temp =set[j];
set[j] = yRoot;
j = temp;
}
set[j] = yRoot;*/
set[xRoot] = yRoot;
count[yRoot] += count[xRoot];
}
}
}