Nearest Common Ancestors

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 20983   Accepted: 11017

Description

A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: 



 

In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor
of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node
x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common
ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is. 



For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest
common ancestor of y and z is y. 



Write a program that finds the nearest common ancestor of two distinct nodes in a tree. 


Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case starts with a line containing an integer N , the number of nodes in a tree, 2<=N<=10,000. The nodes are labeled with integers 1, 2,...,
N. Each of the next N -1 lines contains a pair of integers that represent an edge --the first integer is the parent node of the second integer. Note that a tree with N nodes has exactly N - 1 edges. The last line of each test case contains two distinct integers
whose nearest common ancestor is to be computed.

Output

Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor.

Sample Input

2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5

Sample Output

4
3

在求解近期公共祖先为问题上,用到的是Tarjan的思想,从根结点開始形成一棵深搜树。处理技巧就是在回溯到结点u的时候。u的子树已经遍历。这时候才把u结点放入合并集合中,这样u结点和全部u的子树中的结点的近期公共祖先就是u了,u和还未遍历的全部u的兄弟结点及子树中的近期公共祖先就是u的父亲结点。

这样我们在对树深度遍历的时候就非常自然的将树中的结点分成若干的集合,两个集合中的所属不同集合的随意一对顶点的公共祖先都是同样的,也就是说这两个集合的近期公共祖先仅仅有一个。时间复杂度为O(n+q),n为节点,q为询问节点对数。



#include"stdio.h"
#include"string.h"
#include"vector"
using namespace std;
#define N 11000
const int inf=1<<20;
vector<int>g[N];
int s,t,n;
int f[N],pre[N],ans[N];
bool vis[N];
int findset(int x)
{
if(x!=f[x])
f[x]=findset(f[x]);
return f[x];
}
int unionset(int a,int b)
{
int x=findset(a);
int y=findset(b);
if(x==y)
return x;
f[y]=x;
return x;
}
void lca(int u)
{
int i,v;
ans[u]=u;
for(i=0;i<g[u].size();i++)
{
v=g[u][i]; //訪问由父节点引出的各个子节点
lca(v);
int x=unionset(u,v); //把父子节点合并
ans[x]=u; //祖先节点记为U
}
vis[u]=1;
if(u==s&&vis[t]) //两个节点依次被訪问标记,第二次訪问时才满足条件
{
printf("%d\n",ans[findset(t)]);
return ;
}
else if(u==t&&vis[s])
{
printf("%d\n",ans[findset(s)]);
return ;
}
}
int main()
{
int i,u,v,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
pre[i]=-1; //记录节点I的父节点
f[i]=i; //并查集记录根节点
vis[i]=0;
g[i].clear();
}
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
pre[v]=u;
}
scanf("%d%d",&s,&t);
for(i=1;i<=n;i++)
if(pre[i]==-1)
break;
lca(i);
}
return 0;
}



版权声明:本文博客原创文章,博客,未经同意,不得转载。

LCA 学习算法 (最近的共同祖先)poj 1330的更多相关文章

  1. [最近公共祖先] POJ 1330 Nearest Common Ancestors

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27316   Accept ...

  2. POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)

    /* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...

  3. POJ 1330 Nearest Common Ancestors 倍增算法的LCA

    POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节 ...

  4. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  5. POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14902   Accept ...

  6. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...

  7. 最近公共祖先LCA(Tarjan算法)的思考和算法实现

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...

  8. 最近公共祖先 LCA 倍增算法

          树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...

  9. POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)

    题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...

随机推荐

  1. Java线程的生命周期(转)

    Java线程的生命周期 一个线程的产生是从我们调用了start方法开始进入Runnable状态,即可以被调度运行状态,并没有真正开始运行,调度器可以将CPU分配给它,使线程进入Running状态,真正 ...

  2. 极路由1s,固件需要刷入RipOS系统的加40块

    极路由1s,固件需要刷入RipOS系统的加40块,集成wifidog功能,wifi广告路由器的理想选择功能. 经过测试,无线性能稳定,无线可带32个手机客户端. 具体配置: 7620CPU ,主频58 ...

  3. 内存数据网格IMDG简单介绍

    1 简单介绍 将内存作为首要存储介质不是什么新奇事儿,我们身边有非常多主存数据库(IMDB或MMDB)的样例.在对主存的使用上.内存数据网格(In Memory Data Grid,IMDG)与IMD ...

  4. vim php代码规范

    vim 代码规范工具php-cs-fixer.phar (參考https://github.com/FriendsOfPHP/PHP-CS-Fixer) INSTALL curl http://get ...

  5. C++--allocator类的使用

    C++为我们提供了安全的内存空间申请方式与释放方式,可是new与delete表达式却是把空间的分配回收与对象的构建销毁紧紧的关联在一起.实际上,作为与C语言兼容的语言,C++也为我们提供了更加底层的内 ...

  6. 服务器编程入门(10)TCP回射服务器实现 - 并发

    问题聚焦:     在前面我们大概浏览了一下服务器编程需要掌握的一些知识和技术,以及架构思想.        实践,才是检验真理的唯一标准..从这节起我们将在这些技术的基础上,一步步实现以及完善一个服 ...

  7. PPP协议总结

    PPP协议总结 PPP协议是一种在点到点链路上传输.封装网络数据包的数据链路层协议,PPP支持同步/异步方式的链路上. 一. PPP支持的链路类型 1. 同步和异步专线 2. 同步拨号链路. 3. 异 ...

  8. poj1947(树形dp)

    题目链接:http://poj.org/problem?id=1947 题意:给n(n<=150)个点的一棵树,求删掉最少边数k使得最后该树只剩下p(1<=p<=n)个节点.(求最小 ...

  9. SVN中正确的add操作和delete操作

    add操作: delete操作:

  10. cocos2D-x 3.5 引擎解析之--引用计数(Ref),自己主动释放池(PoolManager),自己主动释放池管理器( AutoreleasePool)

    #include <CCRef.h> Ref is used for reference count manangement. If a classinherits from Ref. C ...