Codeforces Round #620 (Div. 2)E LCA

题:https://codeforces.com/contest/1304/problem/E

题意:给定一颗树,边权为1,m次询问,每次询问给定x,y,a,b,k,问能否在原树上添加x到y的边,a到b的路径长度等于k,注意这里的点和边都是可以重复走的;

分析:注意到点边可以重复走,我们就可以推出一个条件就是a、b之间的长度len要满足>=k;

   其次当路长大于k时,我们就要判断len和k是否同奇偶,因为要到达长度len要被分为:len=k+2*i(i>=0),否则无法构造出这么一条路径

   然后添加x-y造成的路径选择,有分为最简单的3种

   1、直接走a,b;

   2、走a-x-y-b;

   3、走a-y-x-b;

   然后树上路径就用倍增lca模板即可求俩点间距离

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define pb push_back
const int M=2e5+4;
const int N=20;
struct node{
    int v,w;
    node(int vv=0,int ww=0):v(vv),w(ww){}
};
vector<node>e[M];
int s,grand[M][N],dis[M][N],deep[M],root,n;
void dfs(int u){
    for(int i=1;i<=s;i++){
        grand[u][i]=grand[grand[u][i-1]][i-1];
        dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
        if(!grand[u][i])
            break;
    }
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i].v;
        if(v!=grand[u][0]){
            grand[v][0]=u;
            deep[v]=deep[u]+1;
            dis[v][0]=e[u][i].w;
            dfs(v);
        }   // cout<<"!!"<<endl;
    }
}
void init(){
    s=floor(log(1.0*n)/log(2.0));
    deep[0]=-1;
    dfs(root);
}
int LCA(int a,int b){
    if(deep[a]>deep[b])
        swap(a,b);
    int ans=0;
    for(int i=s;i>=0;i--){
        if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]])
            ans+=dis[b][i],b=grand[b][i];
    }
    for(int i=s;i>=0;i--)
        if(grand[a][i]!=grand[b][i])
            ans+=dis[a][i]+dis[b][i],b=grand[b][i],a=grand[a][i];
    if(a!=b)
        ans+=dis[a][0]+dis[b][0];
    return ans;
}
bool check(int a,int b){
    return b>=a&&(a%2)==(b%2); 
}
int main(){

    scanf("%d",&n);
    for(int v,u,i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        e[u].pb(node(v,1));
        e[v].pb(node(u,1));
    }
    root=1;
    init();
    int m;
    scanf("%d",&m);
    while(m--){
        int x,y,a,b,k;
        scanf("%d%d%d%d%d",&x,&y,&a,&b,&k);
    ///    cout<<LCA(a,b)<<endl;
        if(check(LCA(a,b),k)||check(LCA(a,x)+1+LCA(y,b),k)||check(LCA(a,y)+1+LCA(x,b),k))
            puts("YES");
        else
            puts("NO");
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/starve/p/12331987.html
今日推荐