1.
小团无路可逃
小团惹小美生气了,小美要去找小团“讲道理”。小团望风而逃,他们住的地方可以抽象成一棵有n个结点的树,小美位于x位置,小团位于y位置。小团和小美每个单位时间内都可以选择不动或者向相邻的位置转移,很显然最终小团会无路可逃,只能延缓一下被“讲道理”的时间,请问最多经过多少个单位时间后,小团会被追上。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
输入第一行包含三个整数n,x,y,分别表示树上的结点数量,小美所在的位置和小团所在的位置。
接下来有n-1行,每行两个整数u,v,表示u号位置和v号位置之间有一条边,即u号位置和v号位置彼此相邻。(1<=n<=50000)
输出描述:
输出仅包含一个整数,表示小美追上小团所需的时间。
示例1
输入例子:
5 1 2 2 1 3 1 4 2 5 3
输出例子:
2
解答
双向广搜,以各自为根,追捕者正常广搜,遇到逃脱者的地盘直接占领。逃脱者广搜时不能进入追捕者领域。当自己的领域全部被吞占时,结束。
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();
int x = in.nextInt();
int y = in.nextInt();
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < n-1; i++) {
int a = in.nextInt();
int b = in.nextInt();
List<Integer> list = map.getOrDefault(a, new ArrayList<>());
list.add(b);
map.put(a, list);
list = map.getOrDefault(b, new ArrayList<>());
list.add(a);
map.put(b, list);
}
Set<Integer> xPass = new HashSet<>();
xPass.add(x);
Set<Integer> xNow = new HashSet<>();
Set<Integer> xNext = new HashSet<>();
xNow.add(x);
Set<Integer> yPass = new HashSet<>();
yPass.add(y);
Set<Integer> yLZ = new HashSet<>();
yLZ.add(y);
Set<Integer> yNow = new HashSet<>();
Set<Integer> yNext = new HashSet<>();
yNow.add(y);
int res = 0;
while (true) {
for (Integer i : yNow) { // y先走
List<Integer> list = map.get(i);
for (Integer j : list) {
if (!yPass.contains(j) && !xNow.contains(j)) { // 不能走进小美的势力范围
yPass.add(j);
yNext.add(j);
yLZ.add(j);
}
}
}
if(!yNext.isEmpty()){ // 无路可走
yNow = yNext;
yNext = new HashSet<>();
}
for (Integer i : xNow) { // y先走
List<Integer> list = map.get(i);
for (Integer j : list) {
if ( !xPass.contains(j)) {
xNext.add(j);
xPass.add(j);
if(yNow.contains(j)){
yNow.remove(j);
}
if(yLZ.contains(j)){
yLZ.remove(j);
}
}
}
}
res++;
if(yLZ.isEmpty()){ // 无立足之地
break;
}
xNow = xNext;
xNext = new HashSet<>();
}
System.out.println(res);
}
}
}