#树上最短路研究 洛谷P3398 仓鼠找sugar

问题:给定四个节点(a,b),(c,d),考虑(a,b)的树上最短路与(c,d)的树上最短路是否有交点;

思路一:

如果存在交点,(a,b)或者(c,d)的LCA必定在另一条路径上!

设(a,b),(c,d)之间存在相交的一段路径(e,f)

也即是(e,f)是路径a,b;c,d的一个子集

如果(a,b)的LCA在(e,f)上,则显然有LCA(e,f)=LCA(a,b);

因为如果e,f的LCA不是a,b的LCA,而LCA(a,b)在(e,f)上,那么e,f的LCA深度必然比a,b的小,那么a,b,的LCA就应该是e,f的了!

而(e,f)有同时是c,d的一段,同理,LCA(c,d)=LCA(e,f)=LCA(a,b);

因此c,d的LCA在a,b的路径上且即使a,b的LCA

如果(a,b)的LCA不在(e,f)上

令LCA(a,b)=x,LCA(c,d)=y;

 

 

#include<cstdio>
using namespace std;
const int N=100002;
struct node{
int next;
int to;
}e[N<<1];
int head[N],num,n,q,dep[N],son[N],size[N],top[N];
void addedge(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
inline int read()
{
char ch;
int sign=1,res;
while((ch=getchar())>'9'||ch<'0')
if(sign=='-') sign=-1;
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return res*sign;

}
int x,y;
void dfs1(int u,int f)
{
size[u]=1;
dep[u]=dep[f]+1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v!=f)
{
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int f)
{
if(son[u])
{
top[son[u]]=top[u];
dfs2(son[u],u);
}
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(!top[v])
{
top[v]=v;
dfs2(v,u);
}
}
return;
}
void swap(int &a,int &b)
{
int c=a;
a=b;
b=c;
return;
}
int ask(int x,int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])
swap(x,y),swap(fx,fy);
x=fx;
fx=top[x];
}
if(dep[x]>dep[y])
swap(x,y);
return x;
}
bool find(int a,int b,int c,int d)
{
int lca1=ask(a,b),lca2=ask(c,d);
if(dep[lca1]>dep[lca2])
{
swap(lca1,lca2);
swap(a,c);
swap(b,d);
}
if(ask(lca2,a)==lca2||ask(lca2,b)==lca2)
return true;
else
return false;
}
int a,b,c,d;
int main()
{
n=read();
q=read();
for(int i=1;i<=n-1;i++)
{
x=read();
y=read();
addedge(x,y);
addedge(y,x);
}
dfs1(1,0);
dfs2(1,0);
for(int i=1;i<=q;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(find(a,b,c,d))
printf("Y\n");
else
printf("N\n");
}
return 0;
}

 

容易知道:x的深度比LCA(e,f)要小

而容易知道:e,f的深度比c,d要小,那么

必然有y=LCA(e,f)

也即是y在(a,b)上

综合,当存在交集时,深度较深的LCA必然在深度较浅的LCA的路径上!

那么如何验证一个点是否是在一条路径上呢?

1.计算出这个点到两个端点的距离和,如果等于两点长度,则在

2.对于路径(s,t)

如果LCA(s,x)=x或LCA(t,x)=x成立,则在

 

posted @ 2019-10-25 11:41  会飞的字符串  阅读(137)  评论(0)    收藏  举报