给定一棵树求任意两个节点的公共祖先

tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断。如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果访问过的话,那么它的最近公共祖先就是当前节点祖先。

下面是tarjan离线模板:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = ; struct Edge {
int to, next;
}edge[maxn * ];
//查询
struct Query {
int q, next;
int index;
}query[maxn * ]; int tot, head[maxn];
//查询的前向星
int cnt, h[maxn];
//查询的答案保存在ans中
int ans[maxn * ];
int fa[maxn];//并查集
int r[maxn];//并查集集合个数
int ancestor[maxn];//祖先
bool vis[maxn];//访问标记
int Q;//查询总数
void init(int n)
{
tot = ;
cnt = ;
Q = ;
memset(h, -, sizeof(h));
memset(head, -, sizeof(head));
memset(fa, -, sizeof(fa));
memset(ancestor, , sizeof(ancestor));
memset(vis, false, sizeof(vis));
for (int i = ; i <= n; i++) r[i] = ;
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void addquery(int u, int v, int index)
{
query[cnt].q = v;
query[cnt].index = index;
query[cnt].next = h[u];
h[u] = cnt++;
}
int find(int x)
{
if (fa[x] == -) return x;
return fa[x] = find(fa[x]);
}
void Union(int x, int y)
{
int t1 = find(x);
int t2 = find(y);
if (t1 != t2)
{
if (t1 < t2)
{
fa[t1] = t2;
r[t2] += r[t1];
}
else
{
fa[t2] = t1;
r[t1] += r[t2];
}
}
}
void LCA(int u)//tarjan离线算法
{
vis[u] = true;
ancestor[u] = u;
for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].to;
if (vis[v]) continue;
LCA(v);
Union(u, v);
ancestor[find(u)] = u;
}
for (int i = h[u]; i != -; i = query[i].next)
{
int v = query[i].q;
if (vis[v])
{
ans[query[i].index] = ancestor[find(v)];
}
}
}
bool in[maxn];
int main()
{
int T, n;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
init(n);
memset(in, false, sizeof(in));
int u, v;
for (int i = ; i < n; i++)
{
scanf("%d %d", &u, &v);
in[v] = true;
addedge(u, v);
addedge(v, u);
}
scanf("%d %d", &u, &v);
addquery(u, v, Q);//添加查询
addquery(v, u, Q++);
int root;
for (int i = ; i <= n; i++)
{
if (!in[i])
{
root = i;
break;
}
}
LCA(root);
for (int i = ; i < Q; i++)//按照顺序打印出来答案
printf("%d\n", ans[i]);
}
return ;
}

RMQ&LCA在线模板:

RMQ st算法是用来求一段连续的区间最值问题的,如果将树看成一个线性结构,那么它可以快速求出一段区间的最值,那么就可以利用它求出LCA,首先求出一个树的欧拉序列(就是dfs序),然后每个节点都有深度,都有到根节点的距离。保存一个第一次访问到某个节点的编号。这样求两个点的LCA就是求从欧拉序列当中的一段到另外一段(连续的)深度的最小值。直接RMQ就可以了。模板如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm> using namespace std;
typedef long long ll;
const int maxn = ;
int tot, head[maxn];
struct Edge {
int to, next;
}edge[maxn];
int occur[maxn];
int first[maxn];
int dep[maxn];
bool vis[maxn];
int m;
void init()
{
tot = ;
memset(head, -, sizeof(head));
memset(vis, false, sizeof(vis));
memset(first, , sizeof(first));
m = ;
}
void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u, int depth)
{
occur[++m] = u;
dep[m] = depth;
if (!first[u])
first[u] = m;
for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].to;
dfs(v, depth + );
occur[++m] = u;
dep[m] = depth;
}
}
int Rmin[maxn * ][];
void RMQ(int n)
{
for (int i = ; i <= n; i++)
Rmin[i][] = i;
int k = (int)log2(n);
for (int j = ; j <= k; j++)
{
for (int i = ; i + ( << j) - <= n; i++)
Rmin[i][j] = dep[Rmin[i][j - ]] < dep[Rmin[i + ( << (j - ))][j - ]] ? Rmin[i][j - ] : Rmin[i + ( << (j - ))][j - ];
}
}
int query(int a, int b)
{
int l = first[a], r = first[b];
if (l > r)
swap(l, r);
int k = (int)log2(r - l + );
int tmp = dep[Rmin[l][k]] < dep[Rmin[r - ( << k) + ][k]] ? Rmin[l][k] : Rmin[r - ( << k) + ][k];
return occur[tmp];
}
int main()
{
int T, n;
scanf("%d", &T);
while (T--)
{
init();
scanf("%d", &n);
int a, b;
for (int i = ; i < n; i++)
{
scanf("%d %d", &a, &b);
addedge(a, b);
vis[b] = true;
}
int root;
for (int i = ; i <= n; i++)
{
if (!vis[i])
{
root = i;
break;
}
}
dfs(root, );
scanf("%d %d", &a, &b);
RMQ(m);
printf("%d\n", query(a, b));
}
return ;
}

POJ 1330 Nearest Common Ancestors(LCA模板)的更多相关文章

  1. POJ.1330 Nearest Common Ancestors (LCA 倍增)

    POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...

  2. POJ 1330 Nearest Common Ancestors LCA题解

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19728   Accept ...

  3. poj 1330 Nearest Common Ancestors lca 在线rmq

    Nearest Common Ancestors Description A rooted tree is a well-known data structure in computer scienc ...

  4. poj 1330 Nearest Common Ancestors LCA

    题目链接:http://poj.org/problem?id=1330 A rooted tree is a well-known data structure in computer science ...

  5. POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)

    /* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...

  6. POJ - 1330 Nearest Common Ancestors(基础LCA)

    POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %l ...

  7. POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)

    POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...

  8. POJ 1330 Nearest Common Ancestors(lca)

    POJ 1330 Nearest Common Ancestors A rooted tree is a well-known data structure in computer science a ...

  9. POJ 1330 Nearest Common Ancestors 倍增算法的LCA

    POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节 ...

随机推荐

  1. php字符串处理函数常见问题

    PHP 的字符串处理功能非常强大,主要包括: 字符串输出 echo():输出一个或多个字符串 print():输出一个字符串 printf():输出格式化字符串 字符串去除 trim():去除字符串 ...

  2. C缩写

    STL:Standard Template Library,标准模板库

  3. Title of live Writer

    Test From Windows Live Writer **markdown bold**

  4. MAC 开发工具

    web开发编辑器 Espresso下载地址   密码: i9hr

  5. 在 LINQ to Entities 查询中无法构造实体或复杂类型

    public List<CustomerType> GetCustomerTypesBySchemaTypeCode(int schemaTypeCode) { var query = ( ...

  6. BZOJ 1019 汉诺塔

    Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体. 对汉诺塔的一次合法的操 ...

  7. 利用多线程资源竞争技术上传shell

    通过多线程资源竞争的手段同时上传两个头像,就可以在Apache+Rails环境下实现远程代码执行.这并不是天方夜谭,同时我相信许多文件上传系统都会有这个漏洞……这是一个非常有趣的安全实验,一起来看看吧 ...

  8. Jenkins安装入门

    这是一次兴奋之旅哈..说不定用得着呢~~~:) 嘿嘿.. 安装很简单,JDK,MAVEN(如果),YUM或RPM包安装JENKINS(因为好像YUM安装好慢,不如RPM下载安装) 参考URL: htt ...

  9. java中的string字符串中的trim函数的作用

    去掉字符串首尾空格 防止不必要的空格导致错误public class test{ public static void main(String[] args) { String str = " ...

  10. 线性代数(高斯消元):JSOI2008 球形空间产生器sphere

    JSOI2008 球形空间产生器sphere [题目描述] 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确 ...