POJ_1330 Nearest Common Ancestors LCA
Posted EricJeffrey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ_1330 Nearest Common Ancestors LCA相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=1330
最近公共祖先模板题
Tarjan离线算法 :
读取所有询问后保存并按照一定方式排列。该算法主要采取深度优先搜索的方式,结合并查集,在搜索同时处理查询,大致过程如下:
搜索到节点u
访问标记u
对于u的所有子节点递归搜索,每搜索并处理完一个子节点后将其与当前节点合并,u为父节点
若有一个与u关联的询问 q(u, v) 并且 v 已经被访问过,则其lca为 find(v) - 即并查集父节点函数
为何lca为 find(v) :
如果有一个从当前结点到结点v的询问,且v已被检查过,则由于进行的是深度优先搜索,当前结点与v的最近公共祖先一定还没有被检查,而这个最近公共祖先的包涵v的子树一定已经搜索过了,那么这个最近公共祖先一定是v所在集合的祖先。
参考:http://dongxicheng.org/structure/lca-rmq/
实际代码编写中需要注意初始化,并查集合并时父节点是否一定等问题,细节处理要谨慎。
伪代码:
1 lca(node u){ 2 fa[u] = u; 3 vis[u] = 1; 4 for every son of u{ 5 lca(u.son) 6 union(u, u.son); 7 } 8 for every query of u { 9 if vis[q[u]] == 1 10 ans[u].push_back(find(q[u])) 11 } 12 }
题目AC代码:
1 const int inf = 0x3f3f3f3f; 2 const int maxn = 1e4 + 5; 3 struct Edge{ 4 int to, next, val; 5 }; 6 Edge edges[maxn * 2]; 7 int tot, head[maxn], vis[maxn]; 8 int n; 9 int fa[maxn]; 10 int qu, qv, ans; 11 int deg[maxn]; 12 13 void init(){ 14 memset(deg, 0, sizeof(deg)); 15 memset(edges, 0, sizeof(edges)); 16 memset(head, -1, sizeof(head)); 17 memset(vis, 0, sizeof(vis)); 18 for(int i = 0; i <= n; i++) fa[i] = i; 19 tot = 0; 20 } 21 void addEdge(int u, int v, int w){ 22 edges[tot].to = v; 23 edges[tot].val = w; 24 edges[tot].next = head[u]; 25 head[u] = tot++; 26 } 27 28 int find(int x){ 29 return (fa[x] == x)? x: fa[x] = find(fa[x]); 30 } 31 void unite(int x, int y){ 32 int fx = find(x), fy = find(y); 33 if(fx == fy) return; 34 fa[fy] = fx; 35 } 36 37 void lca(int u){ 38 fa[u] = u; 39 vis[u] = 1; 40 for(int i = head[u]; i != -1; i = edges[i].next){ 41 if(!vis[edges[i].to]) { 42 lca(edges[i].to); 43 unite(u, edges[i].to); 44 } 45 } 46 if(u == qu && vis[qv] == 1){ 47 ans = find(qv); 48 } 49 if(u == qv && vis[qu] == 1){ 50 ans = find(qu); 51 } 52 } 53 54 55 int main(){ 56 int T; 57 scanf("%d", &T); 58 while(T--){ 59 scanf("%d", &n); 60 init(); 61 for(int i = 0; i < n - 1; i++){ 62 int from, to; 63 scanf("%d %d", &from, &to); 64 deg[to]++; 65 addEdge(from, to, 1); 66 addEdge(to, from, 1); 67 } 68 int root = 1; 69 for(int i = 1; i <= n; i++) if(deg[i] == 0) root = i; 70 scanf("%d %d", &qu, &qv); 71 lca(root); 72 printf("%d\n", ans); 73 } 74 }
题目:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 29509 | Accepted: 15069 |
Description
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
Output
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
以上是关于POJ_1330 Nearest Common Ancestors LCA的主要内容,如果未能解决你的问题,请参考以下文章
POJ 1330 Nearest Common Ancestors LCA题解
poj1330 Nearest Common Ancestors (最近公共祖先)
poj1330 Nearest Common Ancestors
[POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)