poj 1470 lca(tarjan做的)

poj 1470 Closest Common Ancestors

题目:

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:
这里写图片描述

题意:

就是给一个树之后,再给一堆查询,让你找到每个节点当最近公共子节点的个数,为零不输出,查询比较大(似乎50w左右),输入比较吃 * 。

思路:

挺裸的一个题目,用tarjan做的,至于tarjan是什么的话我是看这个的:
http://blog.csdn.net/geniusluzh/article/details/6609685
大概意思就是对树进行一次后序遍历,每次访问到了一个节点a,如果有一个查询的其中一个节点是a,那么看另外一个节点b,如果b节点已经访问过了,那么他们的lca就是b已经访问过的祖先的父节点(因为,在后序遍历中从b到a是从这里转过来的,这里也就是他们的lca)。

我在那个博客了学了一发存查询的姿势,之前存法差不多,但是一直wa。。
这个存法其实把每个查询存了两遍,但是dfs是只有一遍是a,b都已经访问过的了,所以没有问题(代码有一个bug是如果a==b的话会算两遍,然而似乎并没有这种数据)。

顺便一提输入查询比较坑,在poj讨论群找了这个输入,比较机智。
scanf(” (%d %d)”,&x,&y);

代码:

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
#include <stdlib.h>
#define N 940
using namespace std;
vector<int>tree[N];
vector<int>text[N];
bool root[N];
int ans[N];
int father[N];
bool vis[N];
int n,q;
int finds(int i)
{
    if(father[i]==i)
        return i;
    else
        return father[i]=finds(father[i]);
}
void init()
{
    memset(root,1,sizeof(root));
    memset(vis,0,sizeof(vis));
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=n;i++)
    {
        tree[i].clear();
        text[i].clear();
        father[i]=i;
    }
}
void dfs(int cur)
{
    int len=tree[cur].size();
    for(int i=0;i<len;i++)
    {
        int t=tree[cur][i];
        dfs(t);
        father[t]=cur;
    }
    vis[cur]=true;
    len=text[cur].size();
    for(int i=0;i<len;i++)
    {
        int tmp=text[cur][i];
        if(vis[tmp])
            ans[finds(tmp)]++;
    }
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int x,n1,y;
        init();
        for(int i=1;i<=n;i++)
        {
            scanf("%d:(%d)\n",&x,&n1);
            for(int i=1;i<=n1;i++)
            {
                scanf("%d",&y);
                tree[x].push_back(y);
                root[y]=false;
            }
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf(" (%d %d)",&x,&y);
            text[x].push_back(y);
            text[y].push_back(x);
        }
        for(int i=1;i<=n;i++)
            if(root[i])
            {
                dfs(i);
                break;
            }

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

P.S.:改不出bug,宛如咸鱼,(明显就是么)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值