• (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;
    }



  • 相关阅读:
    Azure虚拟机部署Linux+PHP+Swoole
    [经验分享]OBS 如何实现多路推流
    SQL Server 中的登陆用户如何只看到指定的数据库
    NCF 数据库错位导致站点访问不了
    AutoIT+Selenium的使用
    2019年入职体检那些事
    Jmeter 针对工具类的每个方法进行测试
    Effective Jmeter:记录一些场景下有效的解决方案
    通过 Test Fragment + Module Controller 封装登录接口
    在setUp线程组中初始化全局工具类
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/5686225.html
Copyright © 2020-2023  润新知