Nearest Common Ancestors
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 30147   Accepted: 15413

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

Source

 
题目大意:
输入T组数据,
然后输入n个节点,
紧接着输入n-1条边 x y,表示x是y的父亲节点
最后输入要询问的 s,t
求s t的最近公共祖先
题解:LCA
 
#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
const int logN=;
vector<int> G[N];
int root;
int parent[][N];
int fa[N],n,x,y,s,t;
int depth[N]; void dfs(int v,int p,int d)
{
parent[][v]=p;
depth[v]=d;
for(int i=;i<G[v].size();i++)
if (G[v][i]!=p)
{
fa[G[v][i]]=v;
dfs(G[v][i],v,d+);
}
}
void init(int V)
{
int root;
for(int i=;i<=n;i++)
if (fa[i]==) {root=i; break;}
dfs(root,-,);
for(int k=;k+<logN;k++)
{
for(int v=;v<=V;v++)
{
if(parent[k][v]<) parent[k+][v]=-;
else parent[k+][v]=parent[k][parent[k][v]];
}
}
}
int lca(int u,int v)
{
if (depth[u]>depth[v]) swap(u,v);
for(int k=;k<logN;k++)
{
if ((depth[v]-depth[u])>>k & )
v=parent[k][v];
}
if (u==v) return u;
for(int k=logN-;k>=;k--)
{
if (parent[k][u]!=parent[k][v])
{
u=parent[k][u];
v=parent[k][v];
}
}
return parent[][u];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) {G[i].clear(); fa[i]=;}
for(int i=;i<=n-;i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
fa[y]=x;
}
init(n);
scanf("%d%d",&s,&t);
int croot=lca(s,t);
printf("%d\n",croot);
}
return ;
}

ST&RMQ  的LCA

#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=;
const int M=;
int tot,cnt,n,T,s,t;
int head[N]; //记录i节点在e数组中的其实位置
int ver[*N]; //ver:保存遍历的节点序列,长度为2n-1,从下标1开始保存
int R[*N]; // R:和遍历序列对应的节点深度数组,长度为2n-1,从下标1开始保存
int first[N]; //first:每个节点在遍历序列中第一次出现的位置
bool vis[N]; //遍历时的标记数组
int dp[*N][M],fa[N]; struct edge
{
int u,v,next;
}e[*N];
void dfs(int u ,int dep)
{
vis[u] = true;
ver[++tot] = u;
first[u] = tot;
R[tot] = dep;
for(int k=head[u]; k!=-; k=e[k].next)
if( !vis[e[k].v] ) //这里可以省个vis数组,如果在dfs改成dfs(当前节点,当前节点的父亲,当前节点的深度) 具体可以参照connections with cities {
int v=e[k].v;
dfs(v,dep+);
ver[++tot]=u;
R[tot]=dep;
}
}
void ST(int n)
{
for(int i=;i<=n;i++)
dp[i][] = i;
for(int j=;(<<j)<=n;j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
int a = dp[i][j-] , b = dp[i+(<<(j-))][j-];
dp[i][j] = R[a]<R[b]?a:b;
}
}
} int RMQ(int l,int r)
{
int k=(int)(log((double)(r-l+))/log(2.0));
int a = dp[l][k], b = dp[r-(<<k)+][k]; //保存的是编号
return R[a]<R[b]?a:b;
} int LCA(int u ,int v)
{
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
} void addedge(int u,int v)
{
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(fa,,sizeof(fa));
cnt=; tot=;
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
fa[y]=x;
}
for(int i=;i<=n;i++)
if (fa[i]==) { dfs(i,); break;}
ST(*n-);
scanf("%d%d",&s,&t);
printf("%d\n",LCA(s,t));
}
return ;
}

poj 1330 Nearest Common Ancestors(LCA 基于二分搜索+st&rmq的LCA)的更多相关文章

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

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

  2. POJ - 1330 Nearest Common Ancestors(基础LCA)

    POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %l ...

  3. POJ.1330 Nearest Common Ancestors (LCA 倍增)

    POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...

  4. POJ 1330 Nearest Common Ancestors(lca)

    POJ 1330 Nearest Common Ancestors A rooted tree is a well-known data structure in computer science a ...

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

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

  6. LCA POJ 1330 Nearest Common Ancestors

    POJ 1330 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24209 ...

  7. POJ 1330 Nearest Common Ancestors 【LCA模板题】

    任意门:http://poj.org/problem?id=1330 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000 ...

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

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

  9. POJ 1330 Nearest Common Ancestors(Targin求LCA)

    传送门 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26612   Ac ...

随机推荐

  1. 卸载vs2017

    卸载enterprise版本 Microsoft.FSharp.SDK.Core卸载失败Package 'Microsoft.FSharp.SDK.Core,version=15.7.20180605 ...

  2. 51nod 1137 矩阵乘法

    基本的矩阵乘法 中间for(int j=0;i<n;i++)  //这里写错了   应该是j<n 晚上果然  效率不行 等会早点儿睡 //矩阵乘法 就是 两个矩阵 第一个矩阵的列 等与 第 ...

  3. 51nod 1080 两个数的平方和

    没心情写数学题啦啊   好难啊 #include<bits/stdc++.h> using namespace std; set<int> s; set<int>: ...

  4. spring实现定时任务的两种方式

    本文为博主原创,未经允许不得转载 项目中要经常事项定时功能,在网上学习了下用spring的定时功能,基本有两种方式,在这里进行简单的总结, 以供后续参考,此篇只做简单的应用. 1.在spring-se ...

  5. java面试项目经验:框架及应用

    Java项目经验 Java就是用来做项目的!Java的主要应用领域就是企业级的项目开发!要想从事企业级的项目开发,你必须掌握如下要点:1.掌握项目开发的基本步骤2.具备极强的面向对象的分析与设计技巧3 ...

  6. 分布式事务之——tcc-transaction分布式TCC型事务框架搭建与实战案例(基于Dubbo/Dubbox)

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/73731363 一.背景 有一定分布式开发经验的朋友都知道,产品/项目/系统最初为了 ...

  7. UVa 10603 倒水问题

    https://vjudge.net/problem/UVA-10603 题意:三个杯子,倒水问题.找出最少倒水量. 思路:路径寻找问题.不难,暴力枚举. #include<iostream&g ...

  8. asp.net <asp:Repeater>下的 asp:LinkButton CommandArgument点击事件

    前台 <asp:Repeater ID="rptData" runat="server" OnItemCommand="rptData_Item ...

  9. MarkChanges: Jmeter

    1. 20180627 调整启动的内存set HEAP=-Xms1024m -Xmx1024m2. 20180627 调整输出格式为xml #jmeter.save.saveservice.outpu ...

  10. Python day17 模块介绍1(time,random)

    module模块和包的介绍(略掉了) 常用模块 # time模块 import time print(time.time())#时间戳,在1970年开始到现在一共多少秒 print(time.gmti ...