luogu 3398 仓鼠找sugar
Posted ifmyt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu 3398 仓鼠找sugar相关的知识,希望对你有一定的参考价值。
题目描述
小仓鼠的和他的基(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”。
输入输出样例
输入样例#1:
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
输出样例#1:
Y
N
Y
Y
Y
说明
本题时限1s,内存限制128M,因新评测机速度较为接近NOIP评测机速度,请注意常数问题带来的影响。
20%的数据$ n<=200,q<=200$
40%的数据 $n<=2000,q<=2000$
70%的数据 $n<=50000,q<=50000$
100%的数据 $n<=100000,q<=100000$
solution
这道题用裸的树剖求$LCA$就可以做出来。
但是我们要判断如何在两天路径上找相同的点。
经过多次画图发现,一条路径上的$LCA$一定会出现在另一条路径上。
所以我们就可以求$LCA$。
那么我们需要判断哪两个条件呢?
设当前点$x$,判断在$a$到$b$这条路径上
1.deep[x]>deep[LCA(a,b)]
2.LCA(x,a)==x||LCA(x,b}==x
这两个条件的意思是
如果$x$比$LCA$要深,并且是两个点任意一个点的祖先,那么一定在这个简单路径上
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 200000;
int n,q;
struct edge
{
int next,to;
} e[N];
int head[N],tot,deep[N],fa[N],size[N],top[N],son[N],id[N],cnt,ind[N],root;
void add(int x,int y)
{
e[++tot].next=head[x];
head[x]=tot;
e[tot].to=y;
}
void dfs1(int x,int f)
{
fa[x]=f;
size[x]=1;
for(int i=head[x]; i; i=e[i].next)
{
int v=e[i].to;
if(v!=f && !deep[v])
{
deep[v]=deep[x]+1;
dfs1(v,x);
size[x]=size[v]+size[x];
if(size[v]>size[son[x]]) son[x]=v;
}
}
}
void dfs2(int x,int topf)
{
id[x]=++cnt;
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=head[x]; i; i=e[i].next)
{
int v=e[i].to;
if(v!=fa[x] && !id[v])
dfs2(v,v);
}
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return deep[x]<=deep[y]? x:y;
}
bool judge(int lca,int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
if(x==lca)return true;
}
return false;
}
int main()
{
cin >> n >> q;
for(int i=1; i<=n-1; i++)
{
int a,b;
cin >> a >> b;
add(a,b);
add(b,a);
}
root=1;
deep[1]=1;
dfs1(1,1);
dfs2(1,1);
while(q--)
{
int a,b,c,d;
cin >> a >> b >> c >> d;
int S=LCA(a,b);
int T=LCA(c,d);
if(S==T)
{
cout<<"Y"<<endl;
continue;
}
if(deep[S]>=deep[LCA(S,T)])cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
以上是关于luogu 3398 仓鼠找sugar的主要内容,如果未能解决你的问题,请参考以下文章