总结
求两点之间的距离------LCA
情况A:a-b的距离
情况B:a-x-y-b的距离
情况C:a-y-x-b的距离
dis<=k&&dis%2==k满足一个即可
之前我一直有一个疑问,为啥不用多跑一个环
假设
如果dis[a,x]+1+dis[y,b]<=dis[a,y]+1+dis[x,a];
那么a到b经过x,y取最短路肯定是dis[a,x]+1+dis[y,b]
dis[a,y]+1+dis[x,a]这种就是跑了一个环的情况,不信,你画图瞧瞧
const int N=3e5+5;
int fat[N][21],h[N];
vector<int>G[N];
void dfs(int x)
{
for(auto v:G[x])
{
if(v==fat[x][0])
continue;
h[v]=h[x]+1;
fat[v][0]=x;
dfs(v);
}
}
int lca(int x,int y)
{
if(h[x]<h[y])
swap(x,y);
for(int i=20;i>=0;i--)
if( (h[x]-h[y])>>i )
x=fat[x][i];
if(x==y)
return x;
for(int i=20;i>=0;i--)
if( fat[x][i]!=fat[y][i] )
x=fat[x][i],y=fat[y][i];
return fat[x][0];
}
int dis(int x,int y)
{
return h[x]+h[y]-h[lca(x,y)]*2;
}
signed main()
{
IOS;
file();
int n;
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
G[x].pb(y);
G[y].pb(x);
}
dfs(1);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
fat[j][i]=fat[ fat[j][i-1] ][i-1];
int m;
cin>>m;
while(m--)
{
int x,y,a,b,k;
cin>>x>>y>>a>>b>>k;
int flag=0;
if(dis(a,b)%2==k%2&&dis(a,b)<=k)
flag=1;
if( (dis(a,x)+1+dis(b,y))%2==k%2 && (dis(a,x)+1+dis(b,y))<=k )
flag=1;
if( (dis(a,y)+1+dis(b,x))%2==k%2 && (dis(a,y)+1+dis(b,x))<=k )
flag=1;
cout<<(flag?"YES":"NO")<<endl;
}
return 0;
}
补充
后面,我自己又想了一下,既然C路径一定要走一个成环(x到y的最短路不为1),那么PA∪PB-PA∩PB==PC的一个环,所以C路径就是算了A路径+一个环路径。
const int N=3e5+5;
int fat[N][21],h[N];
vector<int>G[N];
void dfs(int x)
{
for(auto v:G[x])
{
if(v==fat[x][0])
continue;
h[v]=h[x]+1;
fat[v][0]=x;
dfs(v);
}
}
int lca(int x,int y)
{
if(h[x]<h[y])
swap(x,y);
for(int i=20;i>=0;i--)
if( (h[x]-h[y])>>i )
x=fat[x][i];
if(x==y)
return x;
for(int i=20;i>=0;i--)
if( fat[x][i]!=fat[y][i] )
x=fat[x][i],y=fat[y][i];
return fat[x][0];
}
int dis(int x,int y)
{
return h[x]+h[y]-h[lca(x,y)]*2;
}
signed main()
{
IOS;
// file();
int n;
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
G[x].pb(y);
G[y].pb(x);
}
dfs(1);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
fat[j][i]=fat[ fat[j][i-1] ][i-1];
int m;
cin>>m;
while(m--)
{
int x,y,a,b,k;
cin>>x>>y>>a>>b>>k;
int dis1=dis(a,b),dis2=min(dis(a,x)+dis(y,b),dis(a,y)+dis(x,b))+1;
if(dis1%2==k%2&&dis1<=k||dis2%2==k%2&&dis2<=k)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}