题目描述
小仓鼠的和他的基
(
m
e
i
)
(mei)
(mei)友
(
z
i
)
s
u
g
a
r
(zi)sugar
(zi)sugar住在地下洞穴中,每个节点的编号为
1
n
1~n
1 n。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室
(
a
)
(a)
(a)到餐厅
(
b
)
(b)
(b),而他的基友同时要从他的卧室
(
c
)
(c)
(c)到图书馆
(
d
)
(d)
(d)。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?
小仓鼠那么弱,还要天天被 z z q zzq zzq大爷虐,请你快来救救他吧!
输入格式
第一行两个正整数 n n n和 q q q,表示这棵树节点的个数和询问的个数。
接下来 n − 1 n-1 n−1行,每行两个正整数 u u u和 v v v,表示节点u到节点v之间有一条边。
接下来q行,每行四个正整数 a 、 b 、 c a、b、c a、b、c和 d d d,表示节点编号,也就是一次询问,其意义如上。
输出格式
对于每个询问,如果有公共点,输出大写字母
“
Y
”
“Y”
“Y”;否则输出
“
N
”
“N”
“N”。
输入输出样例
输入
5 5
2 5
4 2
1 3
1 4
5 1 5 1
2 2 1 4
4 1 3 4
3 1 1 5
3 5 1 4
输出
Y
N
Y
Y
Y
说明/提示
本题时限
1
s
1s
1s,内存限制
128
M
128M
128M,因新评测机速度较为接近
N
O
I
P
NOIP
NOIP评测机速度,请注意常数问题带来的影响。
20 20 20%的数据 n < = 200 , q < = 200 n<=200,q<=200 n<=200,q<=200
40 40 40%的数据 n < = 2000 , q < = 2000 n<=2000,q<=2000 n<=2000,q<=2000
70 70 70%的数据 n < = 50000 , q < = 50000 n<=50000,q<=50000 n<=50000,q<=50000
100 100 100%的数据 n < = 100000 , q < = 100000 n<=100000,q<=100000 n<=100000,q<=100000
解题思路
题意:现有
A
,
B
,
C
,
D
A,B,C,D
A,B,C,D四点,判断
A
A
A到
B
B
B的最短路和
C
C
C到
D
D
D的最短路有无交汇
以下为结论:
先套两遍
l
c
a
lca
lca,把
A
A
A和
B
B
B的,
C
C
C和
D
D
D的最近公共祖先求出来,然后求出
A
A
A和
D
D
D,
B
B
B和
C
C
C 中
l
c
a
lca
lca深度最大的,把得到的深度与
A
A
A和
B
,
C
B,C
B,C和
D
D
D的
l
c
a
lca
lca深度作比较。如果都大于等于
A
A
A和
B
B
B,
C
C
C和
D
D
D的
l
c
a
lca
lca深度,则输出
“
Y
”
“Y”
“Y”,否则输出
“
N
”
“N”
“N”
推导:
从上图可以很容易得出:
-
A
→
B
A→B
A→B的
l
c
a
lca
lca是2,深度为2
C → D C→D C→D的 l c a lca lca是1,深度为1
A → D A→D A→D的 l c a lca lca是1,深度为1
B → C B→C B→C的 l c a lca lca是2,深度为2
取
m
a
x
max
max后比较,都是大于等于,输出Y。。。
多推几组数据,就能理解啦↖( ^ ω ^ )↗
代码
#include<bits/stdc++.h>
using namespace std;
int n,q,u,v,k,l,r,ll,rr,a1,a2,a3,a4,dep[100010],f[100010][22],head[100010],lg[100010];
struct c{
int x,next;
}a[200010];
void add(int x,int y){
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void dfs(int x,int fa){
f[x][0]=fa,dep[x]=dep[fa]+1;
for(int i=1;i<=lg[dep[x]];i++)
f[x][i]=f[f[x][i-1]][i-1];
for(int i=head[x];i;i=a[i].next){
int t=a[i].x;
if(t!=fa)
dfs(t,x);
}
}
int LCA(int x,int y){
if(dep[x]>dep[y])
swap(x,y);
while(dep[y]>dep[x])
y=f[y][lg[dep[y]-dep[x]]-1];
if(x==y)
return x;
for(int i=lg[dep[x]]-1;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dfs(1,0);
for(int i=1;i<=q;i++)
{
scanf("%d%d%d%d",&l,&r,&ll,&rr);
a1=dep[LCA(l,r)];
a2=dep[LCA(ll,rr)];
a3=dep[LCA(l,rr)];
a4=dep[LCA(ll,r)];
a4=max(a4,a3);
if(a4>=a1&&a4>=a2)
printf("Y\n");
else printf("N\n");
}
}