• 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
  • 相关阅读:
    UOJ#80. 二分图最大权匹配 模板
    BZOJ2243: [SDOI2011]染色
    LA5713 Qin Shi Huang's National Road System
    BZOJ1977: [BeiJing2010组队]次小生成树 Tree
    LA5009 Error Curves
    BZOJ1013: [JSOI2008]球形空间产生器sphere
    BZOJ2733: [HNOI2012]永无乡
    BZOJ1552: [Cerc2007]robotic sort
    BZOJ3223: Tyvj 1729 文艺平衡树
    网络流24题(24/24)
  • 原文地址:https://www.cnblogs.com/starve/p/12331987.html
Copyright © 2020-2023  润新知