题目大意
何老板与郃德君在玩一款有趣的游戏,游戏虽然简单,他俩仍乐此不疲。
游戏在一个n个节点的地图上进行。游戏地图上有n-1条红色边,图中任意两点可通过红色边相互到达。地图上还有n-1条蓝色边,图中任意两点可通过蓝色边相互到达。
游戏开始时,何老板在x号点,郃德君在y号点。两人轮流操作。每一次操作,玩家可以移动到相邻的点,或者原地不动。何老板只能沿红色边移动,郃德君只能沿蓝色边移动。
如果某一刻,两人位于同一个节点(相遇),游戏结束。如果游戏在第i次操作结束,游戏得分为i。何老板想使得游戏得分尽可能大,郃德君想使游戏得分尽可能小。
游戏双方都很聪明,输出最终的游戏得分。
第一行,三个整数n,x,y
接下来n-1行,每行两个整数,表示一条红色边的两个端点
接下来n-1行,每行两个整数,表示一条蓝色边的两个端点
如果能在有限步内结束游戏,输出得分,否则输出-1
样例
4 1 2
1 2
1 3
1 4
2 1
2 3
1 4
输出:4
3 3 1
1 2
2 3
1 2
2 3
输出:4
4 1 2
1 2
3 4
2 4
1 2
3 4
1 3
输出:2
4 2 1
1 2
3 4
2 4
1 2
3 4
1 3
输出:-1
5 1 2
1 2
1 3
1 4
4 5
2 1
1 3
1 5
5 4
输出:6
思路
显然我们需要建两个独立的树,何老板为red_tree,hdhd为blue_tree
对于这两个树,根节点分别为x,y.
则可预处理出hdhd与何老板到达每个节点的时间(用普通的dfs即可)
如果hdhd比何老板先到i节点,那么何老板一定不可以去i节点。
反之ans=max(ans,2*hdhd到达i节点的时间)
那么-1如何判断呢?
假定老板目前在1号节点,hdhd在4号节点。
老板先手仅可以去2否则会被hdhd直接抓住。
那么hdhd仅可以选择前往3节点上。
那么何老板又会回到1号节点
会一直循环下去…
若3 4 中只有一个节点呢?
何老板会被直接抓住,游戏结束。
所以-1的成立条件为dis(u,v)>2(u,v为原图3,4这类的节点)
dis(u,v)用lca算即可
即dis(u,v)=depth[u]+depth[v]-2*depth[lca(u,v)]
附代码
#include<stdio.h>
#include<bits/stdc++.h>
#define maxn 200005
#define inf 1e9
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline int R()
{
char t=GC;
int x=0;
while(!isdigit(t)) t=GC;
while(isdigit(t)) x=x*10+t-48,t=GC;
return x;
}
using namespace std;
int red_cnt,red_ey[maxn*2],red_elast[maxn],red_ne[maxn*2];
void add_red_edge(int x,int y){
red_cnt++;
red_ey[red_cnt]=y;
red_ne[red_cnt]=red_elast[x];
red_elast[x]=red_cnt;
}
int blue_cnt,blue_ey[maxn*2],blue_elast[maxn],blue_ne[maxn*2];
void add_blue_edge(int x,int y){
blue_cnt++;
blue_ey[blue_cnt]=y;
blue_ne[blue_cnt]=blue_elast[x];
blue_elast[x]=blue_cnt;
}
int f[maxn][20],n,x,y;
inline void go_up(int &p,int x)
{
static int s=ceil(log2(n));
for(int i=0;i<=s;++i)if(x&1<<i) p=f[p][i];
return;
}
int red_depth[maxn],blue_depth[maxn];
void Dfs(int u,int fa){
f[u][0]=fa;
int k=ceil(log2(n));
for(int i=1;i<=k;i++)
f[u][i]=f[f[u][i-1]][i-1];
blue_depth[u]=blue_depth[fa]+1;
for(int i=blue_elast[u];i;i=blue_ne[i]){
int v=blue_ey[i];
if(v!=fa){
Dfs(v,u);
}
}
return;
}
int lca(int u,int v)
{
if(blue_depth[u]<blue_depth[v]) swap(u,v);
go_up(u,blue_depth[u]-blue_depth[v]);
if(u==v) return u;
int s=ceil(log2(n));
for(int i=s;i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}
void dfs(int u,int fa){
red_depth[u]=red_depth[fa]+1;
for(int i=red_elast[u];i;i=red_ne[i]){
int v=red_ey[i];
if(v!=fa&&red_depth[u]<blue_depth[u]){
int LCA=lca(u,v);
int Dep=blue_depth[u]+blue_depth[v]-2*blue_depth[LCA];
if(Dep>2){
printf("-1\n");
exit(0);
}
dfs(v,u);
}
}
return;
}
void init(){
Dfs(y,0);
for (int i=1;i<=n;i++) red_depth[i]=inf;
dfs(x,0);
}
void sc(){
scanf("%d%d%d",&n,&x,&y);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add_red_edge(u,v);
add_red_edge(v,u);
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add_blue_edge(u,v);
add_blue_edge(v,u);
}
}
void work(){
int Ans=0;
for(int i=1;i<=n;i++){
red_depth[i]--;
blue_depth[i]--;
if(red_depth[i]<=blue_depth[i]){
Ans=max(Ans,2*blue_depth[i]);
}
}
printf("%d\n",Ans);
}
int main(){
sc();
init();
work();
return 0;
}