zoukankan      html  css  js  c++  java
  • (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;
    }



  • 相关阅读:
    C# 使用SqlBulkCopy类批量复制大数据 快速导入Excel大量数据
    Git的安装与使用
    未能加载文件或程序集“Microsoft.VisualStudio.Web.PageInspector.Loader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。
    Android SDK Manager不能显示所有包的解决办法
    editor多功能文本框在有些计算机上不能正常加载,解决方法,本人用的是把js调用方法放到<body></body>后面)
    MVC URL参数传递+变为空格解决方法
    SQL 查询不重复数据
    Java基本数据类型取值范围
    统计数组中的逆数对个数
    Docker 安装 ElasticSearch
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/5686225.html
Copyright © 2011-2022 走看看