【POJ 1330 Nearest Common Ancestors】LCA Tarjan算法

题目链接:http://poj.org/problem?id=1330

题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先。

数据范围:n [2, 10000]

思路:从树根出发进行后序深度优先遍历,设置vis数组实时记录是否已被访问。

每遍历完一棵子树r,把它并入以r的父节点p为代表元的集合。这时判断p是不是所要求的u, v节点之一,如果r==u,且v已访问过,则lca(u, v)必为v所属集合的代表元。p==v的情况类似。

我的第一道LCA问题的Tarjan算法,题目只有唯一的一组查询,实现起来非常简洁。

注意题目给树的格式:给出n-1个数对<u, v>,u为v的父节点。因此可以当作有向图用邻接表存储,同时记录各个节点的入度,入度为0的点为树根。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 const int MAX_N = 10005;
 6
 7 int parent[MAX_N];
 8
 9 void init(){
10     for(int i=0; i<MAX_N; i++){
11         parent[i] = i;
12     }
13 }
14 int find(int x){
15     if(parent[x] == x) return x;
16     return parent[x] = find(parent[x]);
17 }
18 void unite(int x, int y){
19     x = find(x);
20     y = find(y);
21     if(x == y) return ;
22     parent[y] = x;
23 }
24 bool same(int x, int y){
25     return find(x) == find(y);
26 }
27
28 vector<int> G[MAX_N];
29 int u, v;
30 int T;
31 int n;
32 int vis[MAX_N];
33 int indeg[MAX_N];
34
35 void dfs(int r){
36     //printf("%d\n", r);
37     for(int i=0; i<G[r].size(); i++){
38         if(!vis[G[r][i]]){
39             dfs(G[r][i]);
40             unite(r, G[r][i]);//孩子合并到父节点
41         }
42     }
43     vis[r] = 1; //后序遍历
44     if(r == u && vis[v]){
45         printf("%d\n", find(v));
46         return ;
47     }else if(r == v && vis[u]){
48         printf("%d\n", find(u));
49         return ;
50     }
51 }
52
53 void lca(){
54     memset(vis, 0, sizeof(vis));
55     init();
56     int r = 0;
57     for(int i=1; i<=n; i++){
58         if(indeg[i]==0){
59             //printf("root : %d\n", i); //入度为0的是树根
60             dfs(i);
61         }
62     }
63 }
64
65 int main()
66 {
67     freopen("1330.txt", "r", stdin);
68     scanf("%d", &T);
69     while(T--){
70         scanf("%d", &n);
71         memset(indeg, 0, sizeof(indeg));
72         for(int i=0; i<MAX_N; i++) G[i].clear();
73         for(int i=0; i<n-1; i++){
74             scanf("%d%d", &u, &v);
75             G[u].push_back(v);//有向图
76             indeg[v]++;
77         }
78         scanf("%d%d", &u, &v);
79         lca();
80     }
81     return 0;
82 }
时间: 2024-07-30 13:50:42

【POJ 1330 Nearest Common Ancestors】LCA Tarjan算法的相关文章

POJ 1330 Nearest Common Ancestors LCA(在线RMQ,离线Tarjan)

链接:http://poj.org/problem?id=1330 题意:只看题目就知道题目是什么意思了,最近公共祖先,求在一棵树上两个节点的最近公共祖先. 思路:求最近公共祖先有两种算法,在线和离线,在线方法是用RMQ求LCA,一句话总结就是在从DFS时,从第一个点到第二个点的最短路径中深度最浅的点就是公共祖先,用RMQ处理,一般问题的最优解决方式的复杂度是O(NlogN)的预处理+N*O(1)的查询.离线方法是Tarjan算法,将所有询问的两个点都记录下来,在DFS过程中不断将每个点自身作为

POJ 1330 Nearest Common Ancestors LCA题解

本题是一个多叉树,然后求两点的最近公共单亲节点. 就是典型的LCA问题.这是一个很多解法的,而且被研究的很透彻的问题. 原始的解法:从根节点往下搜索,若果搜索到两个节点分别在一个节点的两边,那么这个点就是最近公共单亲节点了. Trajan离线算法:首次找到两个节点的时候,如果记录了他们的最低单亲节点,那么答案就是这个最低的单亲节点了. 问题是如何有效记录这个最低单亲节点,并有效根据遍历的情况更新,这就是利用Union Find(并查集)记录已经找到的节点,并及时更新最新访问的节点的当前最低单亲节

poj 1330 Nearest Common Ancestors lca 在线rmq

Nearest Common Ancestors 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.

POJ 1330 Nearest Common ancesters(LCA,Tarjan离线算法)

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.

POJ 1330 Nearest Common Ancestors LCA

题目链接: http://poj.org/problem?id=1330 题意: 给你一颗有根树,最后输入一对数(a,b),叫你求a和b的公共祖先. 裸的lca,数据也很小,拿来练手不错. 题解: 1.tarjan_lca,离线,线性时间复杂度 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6

POJ 1330 Nearest Common Ancestors(LCA模板)

给定一棵树求任意两个节点的公共祖先 tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断.如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果访问过的话,那么它的最近公共祖先就是当前节点祖先. 下面是tarjan离线模板: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn =

POJ 1330 Nearest Common Ancestors 倍增算法的LCA

POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节点的第2j个父亲是多少   这个代码不是我的,转自 邝斌博客 1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-9-5 9:45:17 4 File Name :F

POJ - 1330 Nearest Common Ancestors(基础LCA)

POJ - 1330 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 t

[POJ 1330] Nearest Common Ancestors (朴素方法)

POJ 1330: Nearest Common Ancestors Time Limit: 1000ms Memory Limit: 32Mb 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 fro

POJ 1330 Nearest Common Ancestors(树)

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