Codeforces Round #620 (Div. 2) E. 1-Trees and Queries(LCA)

题目链接:https://codeforces.com/contest/1304/problem/E

题目大意:

  给一棵树,q次询问,问在x和y中加一条边,a能否存在一条路径到达b,且长度恰好为k,一条边可以反复走。

题目思路:

  如果没有加边这个条件的话,可以发现,如果从a到b,路径一定是a到b的最短距离+2*x,因为树上两点间的最短路是固定的,要是走了别的路还得回来一定得算两倍,所以唯一的变数就在于新加入的这条边,所以就再计算一下a先到x,然后走新边到达y,再从y到b行不行,最后再算一下a先到y,然后走新边到达x,再从x到b行不行,有一种行就行,否则就不行。

以下是代码:

#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
const int MAXN = 2e5+5;
const int MOD = 1e9+7;
int f[MAXN][20],d[MAXN],dist[MAXN];
int ver[MAXN],Next[MAXN],head[MAXN];
int n,u,v,t,T,tot;
queue<int>q;
void add(int x,int y){
    
    
    ver[++tot]=y;
    Next[tot]=head[x];
    head[x]=tot;
}
void bfs(){
    
    
    q.push(1);d[1]=1;
    while(q.size()){
    
    
        int x=q.front();q.pop();
        for(int i=head[x];i;i=Next[i]){
    
    
            int y=ver[i];
            if(d[y])continue;
            d[y]=d[x]+1;
            dist[y]=dist[x]+1;
            f[y][0]=x;
            rep(j,1,t){
    
    
                f[y][j]=f[f[y][j-1]][j-1];
            }
            q.push(y);
        }
    }
}
int lca(int x,int y){
    
    
    if(d[x]>d[y])swap(x,y);
    per(i,t,0){
    
    
        if(d[f[y][i]]>=d[x])y=f[y][i];
    }
    if(x==y)return x;
    per(i,t,0){
    
    
        if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int dis(int x,int y){
    
    
    int fa=lca(x,y);
    return dist[x]+dist[y]-2*dist[fa];
}
int main()
{
    
    
    while(cin>>n){
    
    
        tot=0;
        memset(head,0,sizeof(head));
        rep(i,1,n-1){
    
    
            cin>>u>>v;
            add(u,v);
            add(v,u);
        }
        t=(int)(log(n)/log(2))+1;
        bfs();
        cin>>T;
        while(T--){
    
    
            int x,y,a,b,k;
            cin>>x>>y>>a>>b>>k;
            int p=dis(a,b);
            if(k>=p&&(k-p)%2==0){
    
    
                cout<<"YES"<<endl;
                continue;
            }
            p=dis(a,x)+1+dis(y,b);
            if(k>=p&&(k-p)%2==0){
    
    
                cout<<"YES"<<endl;
                continue;
            }
            p=dis(a,y)+1+dis(x,b);
            if(k>=p&&(k-p)%2==0){
    
    
                cout<<"YES"<<endl;
                continue;
            }
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/toohandsomeIeaseId/article/details/104341669