• ZOJ 1141:Closest Common Ancestors(LCA)


    Closest Common Ancestors


    Time Limit: 10 Seconds      Memory Limit: 32768 KB

    Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)

    The data set starts with the tree description, in the form:

    nr_of_vertices
    vertex:(nr_of_successors) successor1 successor2 ... successorn
    ......

    where vertices are represented as integers from 1 to n. The tree description is followed by a list of pairs of vertices, in the form:

    nr_of_pairs
    (u v) (x y) ...

    The input contents several data sets (at least one).

    Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.

    For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times

    For example, for the following tree:

    the program input and output is:


    Input

    5
    5:(3) 1 4 2
    1:(0)
    4:(0)
    2:(1) 3
    3:(0)
    6
    (1,5) (1,4) (4,2)
    (2,3)
    (1,3) (4,3)


    Output

    2:1
    5:5

    题意

    给出一颗树, n 次查询最近公共祖先,输出所有查询所涉及到顶点的次数,未涉及则不输出。

    思路

    LCA模板,在输入查询的时候,用scanf(" (%d,%d)",&x,&y);输入,注意"("左边有一个空格

    不知道为什么在POJ过不了,又是TLE又是MLE又是RE的,UVA,ZOJ,CSU都能过

    代码

    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define ull unsigned long long
    #define ms(a,b) memset(a,b,sizeof(a))
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=1e6+10;
    const int mod=1e9+7;
    const int maxm=3e3+10;
    const int maxq=1e6+10;
    using namespace std;
    struct Edge
    {
        int to,Next;
    }edge[maxm<<1];
    int head1[maxm];
    int tot1;
    int ans[maxm];
    void add_edge(int u,int v)
    {
        edge[tot1].to=v;
        edge[tot1].Next=head1[u];
        head1[u]=tot1++;
    }
    struct Query
    {
        int to,Next;
        int index;
    }query[maxq];
    int head2[maxm];
    int tot2;
    void add_query(int u,int v,int index)
    {
        query[tot2].to=v;
        query[tot2].Next=head2[u];
        query[tot2].index=index;
        head2[u]=tot2++;
    }
    int f[maxm];
    int find(int x)
    {
        if(f[x]!=x)
            f[x]=find(f[x]);
        return f[x];
    }
    void join(int x,int y)
    {
        int dx=f[x],dy=f[y];
        if(dx!=dy)
            f[dy]=dx;
    }
    bool vis[maxm];
    int fa[maxm];
    int num[maxm];
    void LCA(int u)
    {
        fa[u]=u;
        vis[u]=1;
        for(register int i=head1[u];~i;i=edge[i].Next)
        {
            int v=edge[i].to;
            if(vis[v])
                continue;
            LCA(v);
            join(u,v);
            fa[find(u)]=u;
        }
        for(register int i=head2[u];~i;i=query[i].Next)
        {
            int v=query[i].to;
            if(vis[v])
                ans[query[i].index]=fa[find(v)];
        }
    }
    bool isroot[maxm];
    inline void init(int n)
    {
        tot1=0;tot2=0;
        ms(head1,-1);ms(head2,-1);
        ms(vis,0);ms(isroot,true);
        ms(num,0);
        for(register int i=1;i<=n;i++)
            f[i]=i;
    }
    int main(int argc, char const *argv[])
    {
        #ifndef ONLINE_JUDGE
            freopen("/home/wzy/in.txt", "r", stdin);
            freopen("/home/wzy/out.txt", "w", stdout);
            srand((unsigned int)time(NULL));
        #endif
        int n;
        int cnt,h,p;
        while(scanf("%d",&n)==1)
        {
            init(n);
            for(register int i=1;i<=n;i++)
            {
                scanf("%d:(%d)",&h,&cnt);
                for(int j=0;j<cnt;j++)
                    scanf("%d",&p),add_edge(p,h),add_edge(h,p),isroot[p]=false;
            }
            int root;
            for(register int i=1;i<=n;i++)
                if(isroot[i])
                    root=i;
            int q;
            scanf("%d",&q);
            int x,y;
            for(register int i=0;i<q;i++)
            {
                scanf(" (%d,%d)",&x,&y);
                add_query(x,y,i);add_query(y,x,i);
            }
            LCA(root);
            for(register int i=0;i<q;i++)
                num[ans[i]]++;
            for(register int i=1;i<=n;i++)
                if(num[i])
                    printf("%d:%d
    ",i,num[i]);
        }
        #ifndef ONLINE_JUDGE
            cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<" s."<<endl;
        #endif
        return 0;
    }
    View Code
  • 相关阅读:
    python之内置函数
    装饰器原理剖析
    迭代器&生成器&yield异步
    python之文件操作read
    函数的创建,调用,返回值和传参的讲解
    collections之deque【双向队列】与Queue【单向队列】
    collections之命名元组
    collections系列之OrderedDict【有序字典】与DefaultDict【默认字典】
    collections系列之Counter
    对象之int介绍
  • 原文地址:https://www.cnblogs.com/Friends-A/p/11315982.html
Copyright © 2020-2023  润新知