题目描述
小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c)到图书馆(d)。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?
小仓鼠那么弱,还要天天被zzq大爷虐,请你快来救救他吧!
输入格式
第一行两个正整数n和q,表示这棵树节点的个数和询问的个数。
接下来n-1行,每行两个正整数u和v,表示节点u到节点v之间有一条边。
接下来q行,每行四个正整数a、b、c和d,表示节点编号,也就是一次询问,其意义如上。
输出格式
对于每个询问,如果有公共点,输出大写字母“Y”;否则输出“N”。
我们画两棵树YY一下啊,如果这两条路径在树上有交点的话呢,那么这两条路径的长度之和,必然大于等于两个起点和两个终点的路径和,先用spfa处理出距离,然后树剖处理询问
QWQ
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int M=200005;
const int N=100004;
int n,q,x,y,xx,yy,tot,head[M],nex[M],to[M],dis[M];
bool vis[M];
struct tree{
int son,fa,top,sz,s,e,dep;
}tr[N];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void add(int a,int b){
++tot;
nex[tot]=head[a];
head[a]=tot;
to[tot]=b;
}
inline void spfa(int x){
queue<int> q;
q.push(x);
for(int i=1;i<=n;i++) dis[i]=2000000000;
vis[x]=1;
dis[x]=0;
while(!q.empty()){
int dmf=q.front();
q.pop();
for(int i=head[dmf];i;i=nex[i]){
int zhn=to[i];
if(dis[zhn]>dis[dmf]+1){
dis[zhn]=dis[dmf]+1;
if(!vis[zhn]){
vis[zhn]=1;
q.push(zhn);
}
}
}
vis[dmf]=0;
}
}
void dfs1(int u){
tr[u].sz=1;
for(int i=head[u];i;i=nex[i]){
if(to[i]!=tr[u].fa){
tr[to[i]].fa=u;
tr[to[i]].dep=tr[u].dep+1;
dfs1(to[i]);
tr[u].sz+=tr[to[i]].sz;
if(tr[to[i]].sz>tr[tr[u].son].sz)
tr[u].son=to[i];
}
}
}
void dfs2(int u,int top){
tr[u].top=top;
if(tr[u].son){
dfs2(tr[u].son,top);
for(int i=head[u];i;i=nex[i])
if(to[i]!=tr[u].fa&&to[i]!=tr[u].son)
dfs2(to[i],to[i]);
}
}
inline int lca(int x,int y){
int f1=tr[x].top;
int f2=tr[y].top;
while(f1!=f2){
if(tr[f1].dep<tr[f2].dep){
swap(f1,f2);
swap(x,y);
}
x=tr[f1].fa;
f1=tr[x].top;
}
if(tr[x].dep<tr[y].dep) return x;
else return y;
}
inline int cal(int x,int y){
//求两点之间的距离
int fa=lca(x,y);
return dis[x]+dis[y]-2*dis[fa];
}
int main(){
n=read();q=read();
for(int i=1;i<n;i++){
x=read();y=read();
add(x,y);
add(y,x);
}
spfa(1);
dfs1(1);
dfs2(1,1);
for(int i=1;i<=q;i++){
x=read();y=read();
xx=read();yy=read();
if(cal(x,y)+cal(xx,yy)>=cal(x,xx)+cal(y,yy)) puts("Y");
else puts("N");
}
return 0;
}