当输入是
5
2
0 1 2
2 3 4
1 2 //这个是测试集
注意:写这种输入的时候,千万记得!!!!
别复制之后,又跑到最后一行改测试数据,因为很有可能scanner读取就乱码了,会把两次的结果叠在一起
可以复制输入数据,然后最后一行的测试数据自己输入
package realtest;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class huawei {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int j=0;
int k=0;
List<List<Integer>> list = new ArrayList<>(); //用list存
while (sc.hasNextLine())
{
j++;
k--;
if(k==0)
{
break;
}
String line = sc.nextLine();
// 将字符串根据空格进行分隔
String[] strings = line.trim().split(" ");
// 分别将其中的每个数值读出
List<Integer> li=new ArrayList<>();
for(int i=0;i<strings.length;i++) {
li.add(Integer.parseInt(strings[i]));
}
list.add(li);
if(j==3)
{
k=j;
}
}
int n=list.get(0).get(0);
UnionFind unionFind=new UnionFind(n);
for(int i=2;i<list.size()-1;i++)
{
for(int p=1;p<list.get(i).size();p++)
{
unionFind.join(list.get(i).get(0), list.get(i).get(p));
}
}
int size=list.size();
int a=list.get(size-1).get(0);
int b=list.get(size-1).get(1);
boolean f=unionFind.isSame(a,b);
if(!f) System.out.println(-1);
else
{
System.out.println(unionFind.rank[a]+unionFind.rank[b]);
}
}
//并查集
public static class UnionFind {
private int pre[];
private int rank[]; //这里是节点到顶点的高度,当然实际高
public UnionFind(int N) {
pre= new int[N];
rank=new int[N];
for(int i = 0; i < N; i++) {
pre[i] = i;
rank[i]=0;
}
}
public int find(int x) //改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点
return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx
}
public boolean isSame(int x, int y) //判断两个结点是否连通
{
return find(x) == find(y); //判断两个结点的根结点(即代表元)是否相同
}
public boolean join(int x,int y) {
int hx = find(x); //寻找 x的代表元
int hy = find(y); //寻找 y的代表元
if (hx == hy) return false; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,返回 false,表示合并失败;否则,执行下面的逻辑
// if (rank[x] > rank[y]) pre[y] = x; //如果 x的高度大于 y,则令 y的上级为 x
// else //否则
// {
// if (rank[x] == rank[y]) rank[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1
// pre[x] = y; //让 x的上级为 y
// }
pre[y]=x;
rank[y]=rank[pre[y]]+1;
return true;
}
}
}