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:
The
In the figure, each of the node is labeled with a integer from {1, 2,..., 16}. Node 8 is the root of the tree. Node x is a ancestor of node y if node x is in the path between the root and node Y. For example, node 4 was an ancestor of node 16. Node also an ancestor of node 16. As a matter of fact, nodes 8, 4, 16, and + are the ancestors of the node. Remember that a node was 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 the 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 and 7. A node x is called the nearest common ancestor of nodes Y and Z if x are a common ancestor of Y and Z and nearest to Y and Z among their common ancestors. Hence, the nearest common ancestor of nodes and 7 is node 4. Node 4 is nearer-nodes and 7 than node 8 is.
For other examples, the nearest common ancestor of nodes 2 and 3 are node, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and are node 4. The last example, if Y is a ancestor of Z, then the nearest common ancestor of Y and Z are y.
Write A program This finds the nearest common ancestor of the distinct nodes in a tree.
Input
The input consists of T test cases. The number of test cases (T) is given on the first line of the input file. Each test case is starts with a line containing an integer N and the number of nodes in a tree, 2<=n<=10,000. The nodes is labeled with integers 1, 2,..., N. Each of the next N-1 lines contains a pair of integers this represent an edge–the first integer is the parent node of th e second integer. Note that a tree with N nodes have exactly N-1 edges. The last line of all test case contains, distinct integers whose nearest common ancestor are to be computed.
Output
Print exactly one line for each test case. The line should contain the "the integer" 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
Taejon 2002
Test Instructions : T set of data, each set of data gives n points and N-1 edges, each edge gives the parent node first, the last row to query a pair of nodes, output their nearest public ancestor.
idea : Because there is only one query, there is no requirement for the output order. You can use the Offline Tarjan algorithm (dfs+ and set) to solve this problem.
Photo from Hihocoder
After completion, find root, start DFS, each DFS to a point, such as U, the ancestor 1 is marked as U (this time the U node has not been processed, we call it a gray node, the corresponding, not traversed by the node called the White node, the finished node known as the Black node), And then traverse it's son. such as the D node, after its son C node is processed, the C and D nodes are the same set (with the same fa[]:d), and then the ancestors of the collection are marked as D2.
back to D (after the end of the traversal of subtree C) The C point is finished, vis marks 3. This time into D's last son B. Continue down until the a node, because the a node has no son, thus directly becomes the black node. At this time traversing the queries associated with a, such as the LCA of A and C, when C is black, it can be concluded that the answer is the ancestor of C's set (one of the ancestors of the first gray node d,c above c). For example, A and B LCA, at this time B is gray, so always go back to D (subtree B is dyed black), the traversal of the query B is associated with a black node 4.
In summary, it should be possible to understand the reason why Tarjan offline. It is to store all of the queries first, and then in a DFS process, utilize and check the set (Maintenance gray) and DFS sequence (maintain black and white) "by the way" to find out the LCA.
The code is as follows :
/* * ID:J.SURE.1 * PROG: * lang:c++ * *#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <ctime>#include <cmath>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <string>#include <climits>#include <iostream>#define PB push_back#define LL Long Longusing namespace STD;Const intINF =0x3f3f3f3f;Const DoubleEPS =1e-8;/****************************************/Const intN =1e4+5, M =2e4+5;structEdge {intV, next; Edge () {} Edge (int_v,int_next): V (_v), Next (_next) {}}e[m];intHead[n], tot, fa[n];intn, x, y, anc[n];BOOLVis[n], son[n]; vector <int>Q[n];voidInit () {memset(Head,-1,sizeof(head)); tot =0; for(inti =1; I <= N; i++) Fa[i] = i;memset(Vis,0,sizeof(VIS));memset(Son,0,sizeof(son));memset(ANC,0,sizeof(ANC)); for(inti =1; I <= N; i++) Q[i].clear ();}voidAddintUintV) {E[tot] = Edge (V, Head[u]); Head[u] = tot++;}intFind (intx) {if(x! = Fa[x])returnFA[X] = Find (fa[x]);returnx;}voidUnion (intXintY) {intFX = Find (x), FY = find (y);if(FY! = FX) Fa[fy] = FX;}voidDfsintu) {Anc[u] = u; for(inti = Head[u]; ~i; i = e[i].next) {intv = e[i].v; DFS (v); Union (U, v); Anc[find (u)] = u; } Vis[u] =true;intSZ = Q[u].size (); for(inti =0; I < sz; i++) {intv = q[u][i];if(Vis[v]) {printf("%d\n", Anc[find (v)]);return; } }}intMain () {#ifdef j_sureFreopen ("000.in","R", stdin);//freopen ("999.out", "w", stdout);#endif intTscanf("%d", &t); while(t--) {scanf("%d", &n);intU, v; Init (); for(inti =0; I < n1; i++) {scanf("%d%d", &u, &v); Add (U, v); SON[V] =true; }intRoot for(inti =1; I <= N; i++) {if(!son[i]) {root = i; Break; } }scanf("%d%d", &x, &y); Q[x].push_back (y); Q[y].push_back (x); DFS (root); }return 0;}
- The ancestor array ANC is just a temporary array for storing the first gray node up at this point, which is the fa[of the set].
- The ancestor marks u as the color of U. At this point the collection is all gray.
- Vis = 1 means that the backtracking is complete, although the entire DFS has not yet exited, but the following function is simply processing the query, so it can be treated as finished.
- So for each query we need to add X-y meaning y-x these two edges to prevent omission.?
"Lca| Tarjan "POJ-1330 Nearest Common Ancestors