POJ 1330(LCA模板)

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

题意:q次询问求两个点u,v的LCA

思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v)

AC代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<set>
 6 #include<string>
 7 #include<vector>
 8 #include<stack>
 9 #include<queue>
10 using namespace std;
11 typedef long long ll;
12 const int maxbit = 15;
13 const int maxn = 1e4+5;
14 vector<int> G[maxn];
15 int depth[maxn];
16 int fa[maxn][maxbit];
17 int Log[maxn];
18 int N;
19 void pre(){
20     Log[0] = -1;
21     Log[1] = 0,Log[2] = 1;
22     for(int i = 3;i<maxn;i++) Log[i] = Log[i/2] + 1;
23 }
24 void dfs(int cur,int father){//dfs预处理
25     depth[cur] = depth[father] + 1;//当前结点的深度为父亲结点+1
26     fa[cur][0] = father;//更新当前结点的父亲结点
27     for(int j = 1;(1<<j)<=N;j++){//倍增更新当前结点的祖先
28         fa[cur][j] = fa[fa[cur][j-1]][j-1];
29     }
30     for(int i = 0;i<G[cur].size() ;i++){
31         if(G[cur][i] != father) {//dfs遍历
32             dfs(G[cur][i],cur);
33         }
34     }
35 }
36 int LCA(int u,int v){
37     if(depth[u]<depth[v]) swap(u,v);
38     int dist = depth[u] - depth[v];//深度差
39     while(depth[u]!=depth[v]){//把较深的结点u倍增到与v高度相等
40         u = fa[u][Log[depth[u]-depth[v]]];
41     }
42     if(u == v) return u;//如果u倍增到v,说明v是u的LCA
43     for(int i = Log[depth[u]];i>=0;i--){//否则两者同时向上倍增
44         if(fa[u][i]!=fa[v][i]){//如果向上倍增的祖先不同,说明是可以继续倍增
45             u = fa[u][i];//替换两个结点
46             v = fa[v][i];
47         }
48     }
49     return fa[u][0];//最终结果为u v向上一层就是LCA
50 }
51 int main()
52 {
53     int t;
54     pre();
55     scanf("%d",&t);
56     while(t--){
57         scanf("%d",&N);
58         int root ;
59         int in[maxn];
60         for(int i = 0;i<maxn;i++){
61             G[i].clear() ;
62         }
63         memset(in,0,sizeof(in));
64         int u,v;
65         for(int i = 0;i<N-1;i++){
66             scanf("%d%d",&u,&v);
67             in[v] = 1;
68             G[u].push_back(v);
69             G[v].push_back(u);
70         }
71         for(int i = 1;i<=N;i++){//寻树的根结点
72             if(in[i] == 0) {
73                 root = i;
74                 break;
75             }
76         }
77         dfs(root,0);
78         scanf("%d%d",&u,&v);
79         int ans = LCA(u,v);
80         printf("%d\n",ans);
81     }
82     return 0;
83 }
84  

原文地址:https://www.cnblogs.com/AaronChang/p/12203298.html

时间: 2024-11-06 16:00:06

POJ 1330(LCA模板)的相关文章

POJ 1330 LCA最近公共祖先 离线tarjan算法

题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集和dfs染色,先dfs到底层开始往上回溯,边并查集合并 一边染色,这样只要询问的两个点均被染色了,就可以输出当前并查集的最高父亲一定是LCA,因为我是从底层层层往上DSU和染色的,要么没被染色,被染色之后,肯定就是当前节点是最近的 #include <iostream> #include <

POJ 1330 LCA裸题~

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

poj 1330 LCA 最近公共祖先

水题目.直接上代码了. VIEW CODE #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #in

POJ 1330 Nearest Common Ancestors (在线LCA转RMQ)

题目地址:POJ 1330 在线LCA转RMQ第一发.所谓在线LCA,就是先DFS一次,求出遍历路径和各个点深度,那么求最近公共祖先的时候就可以转化成求从u到v经过的点中深度最小的那个. 纯模板题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h&g

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

LCA 算法学习 (最近公共祖先)poj 1330

poj1330 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,处理技巧就是在回溯到结点u的时候,u的子树已经遍历,这时候才把u结点放入合并集合中,这样u结点和所有u的子树中的结点的最近公共祖先就是u了,u和还未遍历的所有u的兄弟结点及子树中的最近公共祖先就是u的父亲结点.这样我们在对树深度遍历的时候就很自然的将树中的结点分成若干的集合,两个集合中的所属不同集合的任意一对顶点的公共祖先都是相同的,也就是说这两个集合的最近公共祖先只有一个.时间复杂度为O(n+q

POJ 1330 Nearest Common Ancestors LCA题解

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

POJ 1330 裸的LCA

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

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过程中不断将每个点自身作为