• (Gym 100685G) Gadget Hackwrench(LCA在线ST)


    Gadget Hackwrench
    time limit per test
    2 seconds
    memory limit per test
    64 megabytes
    input
    standard input
    output
    standard output

    Chip 'n' Dale rescue rangers! But observant viewers know that help is usually required by Chip and Dale themselves. Today you are in the role of cunning Gadget Hackwrench.

    So, Chip and Dale are again in the paws of Fat Cat. He doesn't like rodents much and therefore prepared a treacherous test. He is going to put them to a labyrinth and see if they can escape from it. The labyrinth is actually built as a tree where each edge has fixed direction (by definitiontree is a connected unoriented graph without cycles).

    Gadget has intercepted a talk between Fat Cat and his henchmen about future tests. For each test round she knows the exact location where Chip and Dale are to be put by Fat Cat and the location of an exit. Gadget wants to compute whether they will be able to find an exit for each test.

    Input

    The first line of input contains an integer N (1 ≤ N ≤ 105) — the number of vertices in a graph.

    On the next N - 1 lines of input directed arcs of the tree are given. On the (i + 1)th line integer numbers ai and bi are given (1 ≤ ai, bi ≤ N) denoting an arc from vertex ai to vertex bi. It is guaranteed that arcs a1, a2, ..., an - 1 without orientation form a tree.

    Then a string with integer number M (1 ≤ M ≤ 105) is given — the number of queries to process. Next M lines describe queries: (n + 1 + i)thline contain integers xi and yi (1 ≤ xi, yi ≤ N).

    Output

    For each query please output a separate line containing 'Yes' (without quotes) if graph contains a path between xi and yi, or 'No' (without quotes) in other case.

    Examples
    input
    4 1 2 3 1 4 1 6 1 2 3 2 2 3 4 2 4 3 2 1
    output
    Yes Yes No Yes No No

    由于3 2能够通行而2 3无法通行可知通行有方向上的限制,为了解决这种问题,可以人为地在每一对(u,v)之间加上一个负边,长度为-1,而设原来方向的边为+1,
    那么对于每个lca来说,如果u到lca的距离由wei负边构成,v到lca的距离由正边构成,那么这两个点联通

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define scan(x) scanf("%d",&x)
    #define scan2(x,y) scanf("%d%d",&x,&y)
    #define scan3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    using namespace std;
    const int Max=1e5+10;
    const int E=2e5+10;
    int head[Max],nex[E],pnt[E],cost[E],edge;
    int vex[Max<<1],R[Max<<1],vis[Max],dis[Max],first[Max],tot;
    int n;
    void Addedge(int u,int v,int c)
    {
        pnt[edge]=v;
        cost[edge]=c;
        nex[edge]=head[u];
        head[u]=edge++;
    }
    void dfs(int u,int deep)
    {
        vis[u]=1;
        vex[++tot]=u;
        first[u]=tot;
        R[tot]=deep;
        for(int x=head[u]; x!=-1; x=nex[x])
        {
            int v=pnt[x],c=cost[x];
            if(!vis[v])
            {
                dis[v]=dis[u]+c;
                dfs(v,deep+1);
                vex[++tot]=u;
                R[tot]=deep;
            }
        }
    }
    int dp[Max<<1][25];
    void ST(int n)
    {
        int x,y;
        for(int i=1; i<=n; i++) dp[i][0]=i;
        for(int j=1; (1<<j)<=n; j++)
        {
            for(int i=1; i+(1<<j)-1<=n; i++)
            {
                x=dp[i][j-1];
                y=dp[i+(1<<(j-1))][j-1];
                dp[i][j]=(R[x]<R[y]?x:y);
            }
        }
    }
    int RMQ(int l,int r)
    {
        int k=0,x,y;
        while((1<<(k+1))<=r-l+1) k++;
        x=dp[l][k];
        y=dp[r-(1<<k)+1][k];
        return (R[x]<R[y])?x:y;
    }
    int LCA(int u,int v)
    {
        int x=first[u],y=first[v];
        if(x>y) swap(x,y);
        int res=RMQ(x,y);
        return vex[res];
    }
    int vis2[Max];
    void Init()
    {
        edge=0;
        memset(head,-1,sizeof(head));
        memset(nex,-1,sizeof(nex));
        memset(vis,0,sizeof(vis));
        memset(vis2,0,sizeof(vis2));
    }
    int main()
    {
        int T,Q;
        Init();
        int u,v,c;
        scan(n);
        for(int i=0; i<n-1; i++)
        {
            scan2(u,v);
            Addedge(u,v,1);
            Addedge(v,u,-1);
            vis2[v]=1;
        }
        int root=1;
        for(int i=1; i<=n; i++) if(!vis2[i])
            {
                root=i;
                break;
            }
        tot=0;
        dis[root]=0;
        dfs(root,1);
        ST(2*n);
        scan(Q);
        while(Q--)
        {
            scan2(u,v);
            int lca=LCA(u,v);
            cout<<lca<<endl;
            int depu=R[first[u]]-R[first[lca]];
            int depv=R[first[v]]-R[first[lca]];
            int disu=dis[u]-dis[lca];
            int disv=dis[v]-dis[lca];
            //lca与u之间都要为负边,lca与v之间都要为正边
            //u到lca距离全负,因为u的父亲由负边而来
            //v到lca距离全正
            if(depu==-disu&&depv==disv) puts("Yes");
            else puts("No");
        }
        return 0;
    }



  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/5686225.html
Copyright © 2020-2023  润新知