Closest Common Ancestors【POJ1470】——LCA

Time Limit: 2000MS Memory Limit: 10000K

Description

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)

Input

The data set, which is read from a the std input, 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 ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:

nr_of_pairs

(u v) (x y) …

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

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

Output

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:

Sample 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)

Sample Output

2:1

5:5

Hint

Huge input, scanf is recommended.

Source

Southeastern Europe 2000

求最近公共祖先的裸题

大神的博客

Tarjan算法

#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <algorithm>

using namespace std;

const int Max = 1100;

int n,m;

vector<int>E[Max];

vector<int>S[Max];

int pre[Max];

bool vis[Max];

int num[Max];

int Du[Max];
void Init()
{
    for(int i  =0 ;i<Max;i++)
    {
        E[i].clear(); S[i].clear();

        pre[i] = i; vis[i] = false;

        num[i] = 0; Du[i] = 0 ;
    }
}

int find(int x)
{
    return pre[x]==x?x:pre[x] = find(pre[x]);
}

void dfs(int u)
{
    for(int i = 0 ;i<E[u].size();i++)
    {
        dfs(E[u][i]);

        pre[E[u][i]] = u;
    }

    vis[u] = true;

    for(int i = 0;i<S[u].size();i++)
    {
        if(vis[S[u][i]])
        {
            num[find(S[u][i])]++;
        }
    }
}

int main()
{

    int u,v;

    while(~scanf("%d",&n))
    {
        Init();

        for(int i = 0;i<n;i++)
        {
            scanf("%d:(%d)",&u,&m);

            for(int j =  0;j<m;j++)
            {
                scanf("%d",&v);

                Du[v]++;

                E[u].push_back(v);
            }
        }

        scanf("%d",&m);

        for(int  i = 0;i<m;i++)
        {
            while(getchar()!=‘(‘);

            scanf("%d %d",&u,&v);

            S[u].push_back(v);

            S[v].push_back(u);
        }

        while(getchar()!=‘)‘);

        for(int i = 1;i<=n;i++)
        {
            if(!Du[i])
            {
                dfs(i);
            }
        }

        for(int i = 1;i<=n;i++)
        {
            if(num[i]) printf("%d:%d\n",i,num[i]);
        }

    }
    return 0;

RMQ算法

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

const int Max = 2100;

int RMQ[Max][16];

int e[Max],r[Max],d[Max];

int Du[Max];

bool vis[Max];

int num[Max];

vector<int>E[Max];

void Init()
{
    for(int i = 0;i<Max;i++)
    {
        E[i].clear();

        Du[i] = 0;

        num[i] = 0;

        vis[i] = false;
    }
}

int n,m,tot;

void dfs(int u,int dep)
{
    vis[u] = true;

    e[++tot] = u;

    d[u] = tot;

    r[tot] = dep;

    for(int i = 0;i<(int)E[u].size();i++)
    {
        if(!vis[E[u][i]])
        {
            dfs(E[u][i],dep+1);

            e[++tot] = u;

            r[tot] = dep;

        }

    }
}

void RMQ_Min()
{
    for(int i = 1;i<=tot;i++)
    {
        RMQ[i][0] = i;
    }

    for(int i = 1;i<16;i++)
    {
        for(int j = 1;j<=tot;j++)
        {
            if(j+(1<<i)-1<=tot)
            {
                RMQ[j][i] = r[RMQ[j][i-1]]<r[RMQ[j+(1<<(i-1))][i-1]]?RMQ[j][i-1]:RMQ[j+(1<<(i-1))][i-1];
            }
        }
    }
}

int Find(int u,int v)
{
    if(d[u]>d[v])
        swap(u,v);

    int L = d[u],R = d[v];

    int k = (int)(log(R-L+1)/log(2.0));

    int ans =r[RMQ[L][k]]<r[RMQ[R-(1<<k)+1][k]]?RMQ[L][k]:RMQ[R-(1<<k)+1][k];

    return e[ans];
}

int main()
{
    int u,v;

    while(~scanf("%d",&n))
    {
        Init();

        for(int i= 0 ;i<n;i++)
        {

            scanf("%d:(%d)",&u,&m);

            for(int j = 0;j<m;j++)
            {
                scanf("%d",&v);

                Du[v]++;

                E[u].push_back(v);
            }

        }

        tot = 0;

        for(int i = 1;i<=n;i++)
        {
            if(!Du[i])
            {
                dfs(i,1);

                break;
            }
        }

        RMQ_Min();

        scanf("%d",&m);

        while(m--)
        {
            while(getchar()!=‘(‘);

            scanf("%d %d",&u,&v);

            int ans = Find(u,v);

            num[ans]++;
        }

        while(getchar()!=‘)‘);

        for(int  i =1;i<=n;i++)
            if(num[i]) printf("%d:%d\n",i,num[i]);
    }

    return  0;
}
时间: 2024-08-29 08:12:27

Closest Common Ancestors【POJ1470】——LCA的相关文章

poj 1470 Closest Common Ancestors 【Tarjan 离线 LCA】

题目:poj 1470 Closest Common Ancestors 题意:给出一个树,一些询问.求LCA的个数. 分析:很简单的模板题目,但是模板不够优秀,一直wa...RE,各种错误一下午,终于发现自己模板的漏洞了. AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; #define N 1010 #

POJ1470 Closest Common Ancestors 【Tarjan的LCA】

非常裸的模版题,只是Tarjan要好好多拿出来玩味几次 非常有点巧妙呢,tarjan,大概就是当前结点和它儿子结点的羁绊 WA了俩小时,,,原因是,这个题是多数据的(还没告诉你T,用scanf!=EOF来控制结束),更重要的是和这个和Codeforces不一样,Codeforces的多组数据好像会又一次開始程序似的,不用在程序里面写清零,但这个题是多数据用EOF来控制输入的,多数据在一个文件中都一次输进去了,所以要memset btw,加上一点memset代码,多了700B代码... #incl

POJ 1470 Closest Common Ancestors【最近公共祖先LCA】

题目链接:http://poj.org/problem?id=1470 题目大意:给出一棵树,再给出若干组数(a,b),输出节点a和节点b的最近公共祖先(LCA) 就是很裸的LCA,但是我用的是<挑战程序设计竞赛>上的"基于二分搜索的算法求LCA",我看网上用的都是tarjan算法.但是我的代码不知道为什么提交上去 wrong answer,自己想的很多测试数据也都和题解结果一样,不知道错在哪里,所以把代码保存一下,留待以后解决...... 如果读者有什么建议,希望提出来,

POJ 1470 Closest Common Ancestors 【LCA】

任意门:http://poj.org/problem?id=1470 Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 22519   Accepted: 7137 Description Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pa

poj----(1470)Closest Common Ancestors(LCA)

Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 15446   Accepted: 4944 Description 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

POJ 1470 Closest Common Ancestors LCA题解

本题也是找LCA的题目,不过要求多次查询,一般的暴力查询就必然超时了,故此必须使用更高级的方法,这里使用Tarjan算法. 本题处理Tarjan算法,似乎输入处理也挺麻烦的. 注意: 因为查询的数据会极大,故此使用一个数组记录所有查询数据就会超时的.我就载在这里了.查了好久才想到这点.因为我使用了一个vector容器记录了查询数据,故此每次都循环这组这么大的数据,就超时了.----解决办法:使用一个vector<int> quest来记录查询数组,这样每次都只需要循环某节点的邻接查询点就可以了

POJ 题目1470 Closest Common Ancestors(LCA)

Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 16671   Accepted: 5319 Description 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

POJ 1470 Closest Common Ancestors

传送门 Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 17306   Accepted: 5549 Description 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

POJ 1470 Closest Common Ancestors 采用树结构的非线性表编程

A - Closest Common Ancestors(8.4.9) Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the prog