【POJ1330】Nearest Common Ancestors(树链剖分求LCA)

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

【题意】就是求两个点的最近公共祖先。

【分析】  这题可以用倍增做,这次我用了树剖,感觉还挺好打的,嗯嗯...  感觉是因为不可能跳两条重链都越过LCA,因为一个点向下只连一条重边。所以每次调dep较大的边跳就好了。
int LCA(int a, int b)
{
    while (1)
    {
        if(top[a]==top[b]) return dep[a]<=dep[b]?a:b;
        else if(dep[top[a]]>=dep[top[b]]) a=fa[top[a]];
        else b=fa[top[b]];
    }
}

  就是这样。

  感觉是因为不可能跳两条边都越过LCA的,因为一个点向下只连着一条重边,所以我们每次选短的那一条跳就好了。

  http://www.xuebuyuan.com/552070.html

  这里有详细证明^^^

代码如下:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 #define Maxn 10010
 8 #define INF 100000000
 9
10 int fa[Maxn],first[Maxn],size[Maxn],dep[Maxn],son[Maxn];
11 int w[Maxn],top[Maxn];int wl;
12 bool q[Maxn];
13
14 struct node
15 {
16     int x,y,next;
17 }t[2*Maxn];int len;
18
19 int mymax(int x,int y) {return x>y?x:y;}
20 int mymin(int x,int y) {return x<y?x:y;}
21
22 void ins(int x,int y)
23 {
24     t[++len].x=x;t[len].y=y;
25     t[len].next=first[x];first[x]=len;
26 }
27
28 void dfs1(int x,int f)
29 {
30     fa[x]=f;dep[x]=dep[f]+1;size[x]=1;
31     son[x]=0;
32     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
33     {
34         dfs1(t[i].y,x);
35         size[x]+=size[t[i].y];
36         if(size[t[i].y]>size[son[x]]) son[x]=t[i].y;
37     }
38 }
39
40 void dfs2(int x,int tp)
41 {
42     w[x]=++wl;
43     top[x]=tp;
44     if(size[x]!=1) dfs2(son[x],tp);
45     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
46     {
47         dfs2(t[i].y,t[i].y);
48     }
49 }
50
51 int LCA(int a, int b)
52 {
53     while (1)
54     {
55         if(top[a]==top[b]) return dep[a]<=dep[b]?a:b;
56         else if(dep[top[a]]>=dep[top[b]]) a=fa[top[a]];
57         else b=fa[top[b]];
58     }
59 }
60
61
62
63 int main()
64 {
65     int T;
66     scanf("%d",&T);
67     while(T--)
68     {
69         int n;
70         scanf("%d",&n);
71         memset(first,0,sizeof(first));
72         memset(q,0,sizeof(q));
73         len=0;
74         for(int i=1;i<n;i++)
75         {
76             int x,y,c;
77             scanf("%d%d",&x,&y);
78             q[y]=1;
79             ins(x,y);//ins(y,x);
80         }
81         int root;
82         for(int i=1;i<=n;i++) if(!q[i]) root=i;
83         dep[0]=0;size[0]=0;
84         dfs1(root,0);wl=0;
85         dfs2(root,1);
86         int x,y;
87         scanf("%d%d",&x,&y);
88         printf("%d\n",LCA(x,y));
89     }
90     return 0;
91 }

[POJ1330]

2016-05-08 17:13:07

时间: 2024-12-21 18:36:48

【POJ1330】Nearest Common Ancestors(树链剖分求LCA)的相关文章

P2633|主席树+dfs序+树链剖分求lca+离散化

不知道为什么会RE.. 待补 思路:链上求u和v两点路径第k小利用lca就转变为了 U+V-LCA-FA(LCA) 上的第k小,这因为每个点的主席树的root是从其父转移来的.可以用树链剖分求lca:在dfs序上建立主席树将树上问题转变为区间问题,询问的时候用主席树求区间k小值. 终于能写出这种题了,开心! #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+100; int n,m,e = 1,num,ans=0

树链剖分求LCA

这里先推荐两道练习的裸题 首先是求点 [codevs4605] LCA 就是求两个点的公共祖先,每次询问xor上上一个询问的答案. 先是两遍DFS: dfs1:把dep.siz.son求出来 dfs2:求出top和w siz[v]表示以v为根的子树的节点数 dep[v]表示v的深度(根深度为1) top[v]表示v所在的链的顶端节点 fa[v]表示v的父亲 son[v]表示与v在同一重链上的v的儿子节点 w[v]结点编号 int lca(int x,int y){ while (top[x]!=

【模板】树链剖分求LCA

洛谷3379 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=500010,inf=1e9; 5 int n,m,x,y,root,tot,dep[maxn],son[maxn],size[maxn],fa[maxn],top[maxn],last[maxn]; 6 struct edge{int to,pre;}e[maxn<<1]; 7 inline v

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写

POJ1330 Nearest Common Ancestors【最近公共祖先】【Tarjan-LCA算法】

Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19636Accepted: 10412 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

POJ1330 Nearest Common Ancestors

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24587   Accepted: 12779 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:  In the figure, eac

【LCA|Tarjan】POJ-1330 Nearest Common Ancestors

Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K 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,-

POJ1330 Nearest Common Ancestors(最近公共祖先)(tarjin)

A - Nearest Common Ancestors Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu Submit Status Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figu

poj1330 Nearest Common Ancestors (最近公共祖先)

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24236   Accepted: 12619 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each