题目描述
小明是蓝桥王国的侦探。
这天,他接收到一个任务,任务的名字叫分辨是非,具体如下:
蓝桥皇宫的国宝被人偷了,犯罪嫌疑人锁定在 N 个大臣之中,他们的编号分别为 1∼N。
在案发时这 N 个大臣要么在大厅1,要么在大厅2,但具体在哪个大厅他们也不记得了。
审讯完他们之后,小明把他们的提供的信息按顺序记了下来,一共 M 条,形式如下:
x y,表示大臣 x 提供的信息,信息内容为:案发时他和大臣 y 不在一个大厅。
小明喜欢按顺序读信息,他会根据信息内容尽可能对案发时大臣的位置进行编排。
他推理得出第一个与先前信息产生矛盾的信息提出者就是偷窃者,但推理的过程已经耗费了他全部的脑力,他筋疲力尽的睡了过去。作为他的侦探助手,请你帮助他找出偷窃者!
输入描述
第 11 行包含两个正整数 N,M,分别表示大臣的数量和口供的数量。
之后的第 2∼M+1 行每行输入两个整数 x,y,表示口供的信息。
1≤N,M≤5×105,1≤x,y≤N。
输出描述
输出仅一行,包含一个正整数,表示偷窃者的编号。
输入输出样例
示例 1
输入
4 5
1 2
1 3
2 3
3 4
1 4
输出
2
运行限制
最大运行时间:1s
最大运行内存: 256M
源码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class 蓝桥侦探 {
static class UnionFind{
int[] parent;
int[] rank;
public UnionFind(int n) {
parent=new int[n];
for (int i = 0; i < n; i++) {
parent[i]=i;
}
rank=new int[n];
Arrays.fill(rank, 1);
}
public int find(int ind) {
if(parent[ind]!=ind) parent[ind]=find(parent[ind]);
return parent[ind];
}
public void unite(int ind1,int ind2) {
int root1=find(ind1),root2=find(ind2);
if (root1!=root2) {
if (rank[root1]<rank[root2]) {
int temp=root2;
root2=root1;
root1=temp;
}
parent[root2]=root1;
rank[root1]+=rank[root2];
}
}
public boolean connected(int ind1,int ind2) {
return find(ind1)==find(ind2);
}
}
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] s=br.readLine().split(" ");
int n=Integer.parseInt(s[0]);
int m=Integer.parseInt(s[1]);
UnionFind uf=new UnionFind(n*2+1);
for (int i = 0; i < m; i++) {
s=br.readLine().split(" ");
int x=Integer.parseInt(s[0]);
int y=Integer.parseInt(s[1]);
if (uf.connected(x, y)) {
System.out.println(x);
return;
}else {
uf.unite(x, y+n);
uf.unite(y, x+n);
}
}
}
}