https://vjudge.net/problem/CodeForces-1304E
题目大意:给一棵树,个询问,表示在给加一条边的情况下,问是否存在一条从到的经过了条边的路径,该路径可以多次经过同一个点、同一条边,但是起点必须是,终点必须是(有疑问的可看下样例)。
思路:找到一条从到的路径,设其经过了条边,只要且和的奇偶性相同,就是有解的,因为一条边可以经过多次,所以只要,缺少的边数就可以通过在一条边上循环往复来补足。因为加了一条边,所以路径有三种选择:、、。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct Edge
{
int to,nxt;
}edge[maxn<<1];
int n,m,tot;
int head[maxn],deep[maxn],f[maxn][20],bs[20];
inline void addedge(int u,int v)
{
edge[++tot].to=v,edge[tot].nxt=head[u],head[u]=tot;
}
void dfs(int u,int fa)
{
f[u][0]=fa;
for(int i=1;i<20;i++)
f[u][i]=f[f[u][i-1]][i-1];
int v;
for(int i=head[u];i;i=edge[i].nxt)
{
v=edge[i].to;
if(v==fa)
continue;
deep[v]=deep[u]+1;
dfs(v,u);
}
}
inline int skip(int x,int level)
{
for(int i=19;i>=0;i--)
if(bs[i]&level)
x=f[x][i];
return x;
}
inline int LCA(int u,int v)
{
if(deep[u]<deep[v])
swap(u,v);
u=skip(u,deep[u]-deep[v]);
if(u==v)
return u;
for(int i=19;i>=0;i--)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
inline int dis(int x,int y)
{
int lca=LCA(x,y);
return deep[x]+deep[y]-2*deep[lca];
}
inline bool work(int x,int y,int a,int b,int k)
{
int len=dis(a,b);
if(len<=k&&(len-k)%2==0)
return 1;
len=dis(a,x)+dis(b,y)+1;
if(len<=k&&(len-k)%2==0)
return 1;
len=dis(a,y)+dis(b,x)+1;
if(len<=k&&(len-k)%2==0)
return 1;
return 0;
}
int main()
{
for(int i=0;i<20;i++)
bs[i]=1<<i;
scanf("%d",&n);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v),addedge(v,u);
}
dfs(1,0);
int x,y,a,b,k;
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
printf("%s\n",work(x,y,a,b,k)?"YES":"NO");
}
return 0;
}
来源:CSDN
作者:csu_xiji
链接:https://blog.csdn.net/xiji333/article/details/104878440