【题意】:
小仓鼠的和他的基( m e i mei mei)友( z i zi zi) s u g a r sugar sugar住在地下洞穴中,每个节点的编号为 1 n 1~n 1 n。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室( a a a)到餐厅( b b b),而他的基友同时要从他的卧室( c c c)到图书馆( d d d)。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?
小仓鼠那么弱,还要天天被 z z q zzq zzq大爷虐,请你快来救救他吧!
【思路】:
题意即让我们判断一颗树上的两条路径 ( a , b ) (a,b) (a,b)和 ( c , d ) (c,d) (c,d)有没有交点,这有两中方法:
方法 1 : 1: 1:当两条路径长度和 ≥ \geq ≥两条路径起点之距离 + + +两条路径终点之距离,则两条路径有交点(求 ( x , y ) (x,y) (x,y)距离公式: d e p [ x ] + d e p [ y ] − 2 × d e p [ l c a ( x , y ) ] dep[x]+dep[y]-2 \times dep[lca(x,y)] dep[x]+dep[y]−2×dep[lca(x,y)])
方法 2 : 2: 2:当两条路径有交点时,其中一条路径的 l c a lca lca在另一条路径上(判断一个点 x x x是否在路径 ( s , t ) (s,t) (s,t)上: d e p [ x ] ≥ d e p [ l c a ( s , t ) ] dep[x]\geq dep[lca(s,t)] dep[x]≥dep[lca(s,t)]&& ( l c a ( s , x ) = = x ∣ ∣ l c a ( t , x ) = = t ) (lca(s,x)==x||lca(t,x)==t) (lca(s,x)==x∣∣lca(t,x)==t)
[code of 方法1]:
#include
using namespace std;
const int N=100100;
struct node{
int next,to;
}e[N<<1];int h[N],tot;
inline void add(int a,int b){
e[++tot]=(node){h[a],b};h[a]=tot;
e[++tot]=(node){h[b],a};h[b]=tot;
}
int dep[N],f[N][23];
void dfs_init(int u,int fa){
dep[u]=dep[fa]+1;
for(int i=0;i<21;i++)
f[u][i+1]=f[f[u][i]][i];
for(int i=h[u];i;i=e[i].next){
register int to=e[i].to;
if (to==fa) continue;
f[to][0]=u;dfs_init(to,u);
}
}
inline int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
if (dep[f[x][i]]>=dep[y]){
x=f[x][i];if (x==y) return x;
}
if (x==y) return x;//重要
for(int i=20;i>=0;i--)
if (f[x][i]!=f[y][i]){
x=f[x][i];y=f[y][i];
}
return f[x][0];
}
inline int dis(int a,int b){
return dep[a]+dep[b]-2*dep[lca(a,b)];
}
inline bool check(int a,int b,int c,int d){
if (dis(a,b)+dis(c,d)>=dis(a,c)+dis(b,d))
return true;else return false;
}
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
int n,i,p,a,b,c,d;
int main(){
// freopen("t1.in","r",stdin);
n=read();p=read();
for(i=1;i<n;i++)
add(read(),read());
dfs_init(1,0);
for(i=1;i<=p;i++){
a=read();b=read();c=read();d=read();
// cout<
if (check(a,b,c,d))
printf("Y\n");else printf("N\n");
}
return 0;
}
[code of 方法2]:
#include
using namespace std;
const int N=100100;
struct node{
int next,to;
}e[N<<1];int h[N],tot;
inline void add(int a,int b){
e[++tot]=(node){h[a],b};h[a]=tot;
e[++tot]=(node){h[b],a};h[b]=tot;
}
int dep[N],f[N][22];
void dfs_init(int u,int fa){
dep[u]=dep[fa]+1;
for(int i=0;i<20;i++)
f[u][i+1]=f[f[u][i]][i];
for(int i=h[u];i;i=e[i].next){
register int to=e[i].to;
if (to==fa) continue;
f[to][0]=u;dfs_init(to,u);
}
}
inline int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--)
if (dep[f[x][i]]>=dep[y]){
x=f[x][i];if (x==y) return x;
}
if (x==y) return x;//重要
for(int i=20;i>=0;i--)
if (f[x][i]!=f[y][i]){
x=f[x][i];y=f[y][i];
}
return f[x][0];
}
inline bool check(int a,int s,int t){
register int LCA=lca(s,t);
if (dep[a]>=dep[LCA]&&(lca(s,a)==a||lca(t,a)==a))
return true;else return false;
}
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
int n,i,p,a,b,c,d;
int main(){
// freopen("t1.in","r",stdin);
n=read();p=read();
for(i=1;i<n;i++)
add(read(),read());
dfs_init(1,0);
for(i=1;i<=p;i++){
a=read();b=read();c=read();d=read();
// cout<
if (check(lca(a,b),c,d)||check(lca(c,d),a,b))
printf("Y\n");else printf("N\n");
}
return 0;
}