Closest Common Ancestors---poj1470(LCA+离线算法)

题目链接:http://poj.org/problem?id=1470

题意是给出一颗树,q个查询,每个查询都是求出u和v的LCA;

 

 以下是寻找LCA的预处理过程:

void LCA(u){
    for(u的每个儿子v)  {
        LCA(v);
        union(u,v);//并到一个集合中去
    }
    visit[u]=1;
    for(查询中u的每个儿子v)  {
        if(visit[v])
            u,v的最近公共祖先是father[getfather(v)];
    }
}

详细解释  

图文详解

 本题可以使用预处理的方式,也可以使用离线处理,由于不需要求任意两数之间的LCA所以可以使用离线算法;

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <math.h>

using namespace std;

#define met(a, b) memset(a, b, sizeof(a))
#define N 953
#define INF 0x3f3f3f3f
const int MOD = 1e9+7;

typedef long long LL;

vector<int>G[N];
vector<int>Q[N];

int f[N], ans[N], vis[N];

int Find(int x)
{
    if(x!=f[x])
        return f[x] = Find(f[x]);
    return x;
}

void Union(int x, int y)
{
    int px = Find(x);
    int py = Find(y);

        f[py] = px;
}

void LCA(int u)
{
    for(int i=0, len=G[u].size(); i<len; i++)
    {
        int v = G[u][i];
        LCA(v);
        Union(u, v);
    }
    vis[u] = 1;
    for(int i=0, len=Q[u].size(); i<len; i++)
    {
        int v = Q[u][i];
        if(vis[v])
            ans[f[Find(v)]]++;
    }
}

int main()
{
    int n, root;
    while(scanf("%d", &n) != EOF)
    {
        for(int i=0; i<N; i++)
        {
            G[i].clear();
            Q[i].clear();
        }
        met(vis, 0);

        for(int i=1; i<=n; i++)
        {
            f[i] = i;
            int u, v, cnt;
            scanf("%d:(%d)", &u, &cnt);
            for(int j=1; j<=cnt; j++)
            {
                scanf("%d", &v);
                G[u].push_back(v);
                vis[v] = 1;
            }
        }

        for(int i=1; i<=n; i++)
        if(!vis[i])
        {
            root = i;
            break;
        }

        int q, u, v;

        scanf("%d", &q);

        for(int i=1; i<=q; i++)
        {
            scanf(" (%d%d)", &u, &v);
            Q[u].push_back(v);
            Q[v].push_back(u);
        }

        met(vis, 0);
        met(ans, 0);

        LCA(root);

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

 

时间: 2024-10-31 08:09:37

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 #

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】

任意门: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: 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 1330 Nearest Common Ancestors】LCA Tarjan算法

题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从树根出发进行后序深度优先遍历,设置vis数组实时记录是否已被访问. 每遍历完一棵子树r,把它并入以r的父节点p为代表元的集合.这时判断p是不是所要求的u, v节点之一,如果r==u,且v已访问过,则lca(u, v)必为v所属集合的代表元.p==v的情况类似. 我的第一道LCA问题的Tarjan算法

POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)

题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从树根出发进行后序深度优先遍历,设置vis数组实时记录是否已被访问. 每遍历完一棵子树r,把它并入以r的父节点p为代表元的集合.这时判断p是不是所要求的u, v节点之一,如果r==u,且v已访问过,则lca(u, v)必为v所属集合的代表元.p==v的情况类似. 我的第一道LCA问题的Tarjan算法

POJ 1470 Closest Common Ancestors (在线LCA转RMQ)

题目地址:POJ 1470 LCA模板题..输入有点坑,还有输入的第一个结点不一定是根节点. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include

poj 1470 Closest Common Ancestors LCA

题目链接:http://poj.org/problem?id=1470 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 n

POJ 1470 Closest Common Ancestors LCA题解

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