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>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=10000+10;
int fir[MAXN], F[MAXN<<1], tot, deg[MAXN], rmq[MAXN<<1];
int head[MAXN], cnt;
struct node
{
        int u, v, next;
}edge[30000];
void add(int u, int v)
{
        edge[cnt].v=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
}
void dfs(int u, int dep, int fa)
{
        F[++tot]=u;
        rmq[tot]=dep;
        fir[u]=tot;
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v==fa) continue ;
                dfs(v,dep+1,u);
                F[++tot]=u;
                rmq[tot]=dep;
        }
}
struct ST
{
        int dp[MAXN<<1][30], i, j;
        void init(int n)
        {
                for(i=1;i<=tot;i++){
                        dp[i][0]=i;
                }
                for(j=1;(1<<j)<=tot;j++){
                        for(i=1;i<=tot-(1<<j)+1;i++){
                                dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<j-1)][j-1]]?dp[i][j-1]:dp[i+(1<<j-1)][j-1];
                        }
                }
        }
        int Query(int l, int r)
        {
                if(r<l) swap(l,r);
                int k=0;
                while((1<<k+1)<=r-l+1) k++;
                return rmq[dp[l][k]]<rmq[dp[r+1-(1<<k)][k]]?dp[l][k]:dp[r+1-(1<<k)][k];
        }
}st;
void init()
{
        memset(head,-1,sizeof(head));
        cnt=tot=0;
        memset(deg,0,sizeof(deg));
}
int main()
{
        int t, n, i, u, v;
        scanf("%d",&t);
        while(t--){
                scanf("%d",&n);
                init();
                for(i=1;i<n;i++){
                        scanf("%d%d",&u,&v);
                        add(u,v);
                        add(v,u);
                        deg[v]++;
                }
                for(i=1;i<=n;i++){
                        if(!deg[i]){
                                dfs(i,0,-1);
                                break;
                        }
                }
                st.init(n);
                scanf("%d%d",&u,&v);
                printf("%d\n",F[st.Query(fir[u],fir[v])]);
        }
        return 0;
}
时间: 2024-10-05 05:07:25

POJ 1330 Nearest Common Ancestors (在线LCA转RMQ)的相关文章

poj 1330 Nearest Common Ancestors 【LCA】

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20073   Accepted: 10631 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 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算法

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算法

POJ 1330:Nearest Common Ancestors【lca】

题目大意:唔 就是给你一棵树 和两个点,问你这两个点的LCA是什么 思路:LCA的模板题,要注意的是在并查集合并的时候并不是随意的,而是把叶子节点合到父节点上 #include<cstdio> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #define maxn 10002 #define MOD 1000000007 using names

POJ 1470 Closest Common Ancestors (在线LCA转RMQ)

题目地址:POJ 1470 LCA模板题..输入有点坑,还有输入的第一个结点不一定是根节点. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include

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

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题解

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

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