Poj 1330 nearest common ancestors LCA (online rmq, offline Tarjan)

Source: Internet
Author: User
Tags acos

Link: http://poj.org/problem? Id = 1330

I only read the question to know what the question means. Recently, the common ancestor asked the recent common ancestor on two nodes in a tree.

Idea: There are two algorithms for the recent common ancestor: online and offline. The online method is to use rmq to evaluate the LCA. In a word, when we start from DFS, in the shortest path from the first to the second, the shortest point in depth is the common ancestor, which is processed by rmq. Generally, the optimal solution to the problem is the complexity of O (nlogn) preprocessing + N * O (1) queries. The offline method is the Tarjan algorithm, which records all the two points of inquiry. During the DFS process, each vertex itself is used as the ancestor, and after all the subtree traversal is completed, the ancestor becomes its parent node. If a node is traversed during the process and another point of inquiry about it has been traversed, the ancestor of another point is their common ancestor, although the algorithm is not easy to understand, it is very obvious to look at the code.

Code:

Online algorithm: rmq for LCA

# Include <algorithm> # include <cmath> # include <cstdio> # include <cstdlib> # include <cstring> # include <ctime> # include <ctype. h> # include <iostream> # include <map> # include <queue> # include <set> # include <stack> # include <string> # include <vector> # define EPS 1e-8 # define INF 0x7fffffff # define maxn 10005 # define PI ACOs (-1.0) # define seed 31 // 131,1313 typedef long ll; typedef unsigned long ull; using names Pace STD; int sttable [maxn * 2] [32]; int prelog2 [maxn * 2]; int depth = 0; int d [maxn * 2]; bool vis [maxn]; int bn = 0, B [maxn * 2]; // deep sequence int f [maxn * 2]; // corresponding to the node number in the depth sequence int P [maxn]; // The first position of the node in the depth sequence int dis [maxn]; // distance from the node to the root int head [maxn]; void st_prepare (int n, int * array) {prelog2 [1] = 0; For (INT I = 2; I <= N; I ++) {prelog2 [I] = prelog2 [I-1]; If (1 <prelog2 [I] + 1) = I) prelog2 [I] ++;} For (INT I = n-1; I> = 0; I --) {sttable [I] [0] = Array [I]; for (Int J = 1; (I + (1 <j)-1) <n; j ++) {sttable [I] [J] = min (sttable [I] [J-1], sttable [I + (1 <J-1)] [J-1]) ;}} return ;} int query_min (int l, int R) {int Len = r-L + 1, K = prelog2 [Len]; return min (sttable [l] [K], sttable [R-(1 <k) + 1] [k]);} int point [maxn]; // record the number of the first edge corresponding to each vertex, struct edge {int V; // The connection point, int next; // edge [maxn * 2]; int top; int Init () {memset (VIS, 0, sizeof (VIS )); memset (point,-1, sizeof (point); me Mset (DIS, 0, sizeof (DIS); Top = 0; bn = 0; depth = 0;} int add_edge (int u, int v) {edge [Top]. V = V; edge [Top]. next = point [u]; // Number of the last edge point [u] = Top ++; // The first edge number of the u point is changed to head} void DFS (int u, int FA) {int TMP = ++ depth; B [++ bn] = TMP; F [TMP] = u; P [u] = Bn; for (INT I = point [u]; I! =-1; I = edge [I]. next) {int v = edge [I]. v; If (V = FA) continue; DIS [v] = dis [u] + 1; // edge [I]. v dfs (v, U); B [++ bn] = TMP ;}} int main () {int t; scanf ("% d", & T ); while (t --) {Init (); int tot, root = 0, AA, BB; scanf ("% d", & ToT); For (INT I = 1; I <= tot; I ++) head [I] = I; for (INT I = 1; I <= tot-1; I ++) {scanf ("% d", & aa, & bb); add_edge (AA, BB); add_edge (BB, AA); head [BB] = AA ;} for (INT I = 1; I <= tot; I ++) {If (head [I] = I) {root = I; break ;}} DFS (root, root); st_prepare (TOT * 2-1, B); scanf ("% d", & aa, & bb ); if (P [AA] <p [BB]) cout <F [query_min (P [AA], p [BB])] <Endl; else cout <F [query_min (P [BB], p [AA])] <Endl ;}}
Offline algorithm: Tarjan Algorithm

# Include <algorithm> # include <cmath> # include <cstdio> # include <cstdlib> # include <cstring> # include <ctime> # include <ctype. h> # include <iostream> # include <map> # include <queue> # include <set> # include <stack> # include <string> # include <vector> # define EPS 1e-8 # define INF 0x7fffffff # define maxn 10005 # define PI ACOs (-1.0) # define seed 31 // 131,1313 typedef long ll; typedef unsigned long ull; using names Pace STD; int pre [maxn], point [maxn], point2 [maxn]; bool vis [maxn]; struct edge {int V; // connection point int next; // edge [maxn * 2]; struct query {int V; int W; int next;} Query [maxn]; int top, top2; int Init () {memset (VIS, 0, sizeof (VIS); memset (point,-1, sizeof (point); memset (point2,-1, sizeof (point2); Top = 0; top2 = 0;} int add_edge (int u, int v) {edge [Top]. V = V; edge [Top]. next = point [u]; // The number of the last edge point [u] = Top ++; // The first edge number at the U point is changed to head} int findset (int x) // query the set {If (X! = Pre [x]) {pre [x] = findset (pre [x]); // path compression} return pre [X];} int add_query (int u, int v) {Query [top2]. V = V; Query [top2]. W =-1; Query [top2]. next = point2 [u]; // the ID of the last edge point2 [u] = top2 ++; // the ID of the first edge of the U point is changed to head Query [top2]. V = u; Query [top2]. W =-1; Query [top2]. next = point2 [v]; // ID of the last edge point2 [v] = top2 ++; // The first edge number of the u point is changed to head} int LCA (int u, int f) // current node, parent node {pre [u] = u; // set the current node for (INT I = point [u]; I! =-1; I = edge [I]. next) {If (edge [I]. V = f) continue; LCA (edge [I]. v, U); // search for the subtree pre [edge [I]. v] = u; // merge subtree} vis [u] = 1; // search for vertices in the U point set for (INT I = point2 [u]; i! =-1; I = Query [I]. next) {If (vis [Query [I]. v] = 1) Query [I]. W = findset (Query [I]. v);} return 0;} int main () {int root [maxn]; int t; scanf ("% d", & T); For (int ii = 0; II <t; II ++) {Init (); int tot, r =-1, a, B; scanf ("% d", & ToT ); for (INT I = 1; I <= tot; I ++) Root [I] = I; for (INT I = 0; I <tot-1; I ++) {scanf ("% d", & A, & B); add_edge (a, B); add_edge (B, A); root [B] = ;} for (INT I = 1; I <= tot; I ++) if (root [I] = I) r = I; // The root scanf ("% D", & A, & B); add_query (a, B); LCA (R, R); // cout <top2 <Endl; for (INT I = 0; I <top2; I ++) {If (Query [I]. w! =-1) printf ("% d \ n", Query [I]. W) ;}} return 0 ;}

P.s. In fact, this question is only one query. So we should first record the first point of DFS, record the path, and then find the second point of DFS, record the path. The first point of the two paths is also the common ancestor.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.