POJ 1330 Nearest Common Ancestors(LCA模板)
给定一棵树求任意两个节点的公共祖先
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模板)的更多相关文章
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...
- POJ 1330 Nearest Common Ancestors LCA题解
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19728 Accept ...
- poj 1330 Nearest Common Ancestors lca 在线rmq
Nearest Common Ancestors Description A rooted tree is a well-known data structure in computer scienc ...
- poj 1330 Nearest Common Ancestors LCA
题目链接:http://poj.org/problem?id=1330 A rooted tree is a well-known data structure in computer science ...
- POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)
/* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...
- POJ - 1330 Nearest Common Ancestors(基础LCA)
POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %l ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- POJ 1330 Nearest Common Ancestors(lca)
POJ 1330 Nearest Common Ancestors A rooted tree is a well-known data structure in computer science a ...
- POJ 1330 Nearest Common Ancestors 倍增算法的LCA
POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节 ...
随机推荐
- sphinx 简介以及安装 以及php拓展开启
一 sphinx 简介 在 使用mysql数据库过程中,如果想实现全文检索的优化,可以使用mysql自带全文索引,但是不支持中文..关于sphinx的安装网上很多教程写的都 不错比如:http:/ ...
- TC2.0中怎样调用汇编程序
转载于: TC2.0中怎样调用汇编程序 一.概述 TC是美国BORLAND 公司在IBM PC机上开发的一个高效.优化的C编译程序,它自带高效的全屏幕编辑程序,在集成开发环境下可支持编辑.编译.连接调 ...
- java.lang.String.indexOf()用法
java.lang.String.indexOf(char ch) 方法返回字符ch在指定字符串中第一次出现的下标索引位置 如果字符ch在指定的字符串中找不到,则返回-1 示例: import jav ...
- UpdateLayeredWindow, Layered Windows, codeproject
http://www.codeproject.com/Articles/16362/Bring-your-frame-window-a-shadow http://www.codeproject.co ...
- Compare Version Number
package cn.edu.xidian.sselab.string; /** * * @author zhiyong wang * title: Compare Version Numbers ...
- hibernate 3.* C3P0配置 以及为什么需要连接池!
Hibernate自带的连接池算法相当不成熟. 它只是为了让你快些上手,并不适合用于产品系统或性能测试中. 出于最佳性能和稳定性考虑你应该使用第三方的连接池.只需要用特定连接池的设置替换 hibern ...
- 使用 libevent 和 libev 提高网络应用性能
使用 libevent 和 libev 提高网络应用性能 Martin C. Brown, 作家, Freelance 简介: 构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件, ...
- The Embarrassed Cryptographer(高精度取模+同余模定理)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11435 Accepted: 3040 Description The ...
- oracle中触发器中:new和:old 的使用方法--4
转载▼ create or replace trigger TRI_PrintTest before delete or insert or update on TEST_EXAM --触发事 ...
- 数据结构(Splay平衡树): [NOI2007] 项链工厂
[NOI2007] 项链工厂 ★★★ 输入文件:necklace.in 输出文件:necklace.out 简单对比 时间限制:4 s 内存限制:512 MB [问题描述] T公司是一 ...