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. VMware vSphere服务器虚拟化实验十五 vCenter vShield Manager

    VMware vSphere服务器虚拟化实验十五 vCenter vShield Manager VMware  vShield Manager是专为 VMware vCenter Server 集成 ...

  2. Redis slowlog

    和mongo的slowlog一样,redis中对于操作时间较长(默认为10秒)的命令也会记录下来,不过它将它们保存在redisServer结构中的slowlog这个链表中,新进来的log排在链表头部, ...

  3. Android Application Fundamentals——Android应用程序基础知识

    Application Fundamentals--应用程序基础知识 Key classes--关键类 Activity Service BroadcastReceiver ContentProvid ...

  4. Android在onInterceptTouchEvent与onTouchEvent

    onInterceptTouchEvent: onInterceptTouchEvent是在ViewGroup里面定义的.Android中的layout布局类一般都是继承此类的.onIntercept ...

  5. VMware vSphere 服务器虚拟化之二十八 桌面虚拟化之安装View传输服务器

    VMware vSphere 服务器虚拟化之二十八 桌面虚拟化之安装View传输服务器 View 传输服务器用于管理和简化数据中心与在最终用户本地系统上检出使用的 View 桌面之间的数据传输.必须安 ...

  6. 利用Gearman实现并发查询(Multi-Query)

    这个样例是想从数据库查询出几个结果集,一般的做法是,一个接一个的发送查询,然后汇总结果进行输出. 以下我们利用Gearman的gearman_client_run_tasks实现并发的查询,gearm ...

  7. python语言学习4——使用文本编辑器

    在Python的交互式命令行写程序,好处是一下就能得到结果,坏处是没法保存,下次还想运行的时候,还得再敲一遍. 所以,实际开发的时候,我们总是使用一个文本编辑器来写代码,写完了,保存为一个文件,这样, ...

  8. 在MVC应用程序中动态加载PartialView

    原文:在MVC应用程序中动态加载PartialView 有时候,我们不太想把PartialView直接Render在Html上,而是使用jQuery来动态加载,或是某一个事件来加载.为了演示与做好这个 ...

  9. [置顶] Guava学习之Immutable集合

    Immutable中文意思就是不可变.那为什么需要构建一个不可变的对象?原因有以下几点: 在并发程序中,使用Immutable既保证线程安全性,也大大增强了并发时的效率(跟并发锁方式相比).尤其当一个 ...

  10. Session为空的一种原因

    在维护一份比较老的代码,想改为ajax调用,然后就添加了一个一般处理程序文件,也就是以.ashx结尾的文件,一切都正常,但发现session一直为空,很奇怪 基本的代码如下: public class ...