poj 1330 LCA (倍增+离线Tarjan)
/*
先来个倍增
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 10010
using namespace std;
int T,n,num,head[maxn],st,end,anc,fa[maxn][],dep[maxn],out[maxn],root;
struct node
{
int u,v,t,pre;
}e[maxn*];
void Add(int from,int to)
{
num++;
e[num].u=from;
e[num].v=to;
e[num].pre=head[from];
head[from]=num;
}
void Dfs(int now,int from,int c)
{
fa[now][]=from;
dep[now]=c;
for(int i=head[now];i;i=e[i].pre)
if(e[i].v!=from)
Dfs(e[i].v,now,c+);
}
void Get_fa()
{
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-];
}
int Get_same(int a,int t)
{
for(int i=;i<=t;i++)
a=fa[a][];
return a;
}
int LCA(int a,int b)
{
if(dep[a]<dep[b])swap(a,b);
a=Get_same(a,dep[a]-dep[b]);
if(a==b)return a;
for(int i=;i>=;i--)
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];b=fa[b][i];
}
return fa[a][];
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(head,,sizeof(head));
memset(fa,,sizeof(fa));
memset(out,,sizeof(out));
memset(dep,,sizeof(dep));
num=;root=;
scanf("%d",&n);
int x,y;
for(int i=;i<=n-;i++)
{
scanf("%d%d",&x,&y);
Add(x,y);Add(y,x);
out[y]=;
}
for(int i=;i<=n;i++)
if(out[i]==)root=i;
Dfs(root,root,);
Get_fa();
scanf("%d%d",&st,&end);
anc=LCA(st,end);
printf("%d\n",anc);
}
return ;
}
/*
离线Tarjan
我们Dfs整张图的时候 对于一组u v
我们一定按照 u s v 的顺序跑完
此时u v 在以s为根的子树里
那么我们借助并茶几 将u v的fa 的anc赋值为s
这样我们查询u v 的时候就能找到s
如果我们求 st end 的lca
当我们遍历到st 或者end的时候 只需要判断另一个是不是已经被访问过
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 100010
using namespace std;
int T,n,m,fa[maxn],st,end,anc[maxn];
vector<int>a[maxn];
int root[maxn],f[maxn];
void init()
{
scanf("%d",&n);
int x,y;
for(int i=;i<=n;i++)
{
fa[i]=i;root[i]=;
}
for(int i=;i<=n-;i++)
{
scanf("%d%d",&x,&y);
a[x].push_back(y);
fa[y]=x;root[y]=;
}
}
int find(int x)
{
if(x!=fa[x])fa[x]=find(fa[x]);
return fa[x];
}
void Union(int x,int y)
{
int r1=find(x);
int r2=find(y);
if(r1!=r2)fa[r2]=r1;
}
void LCA(int parent)
{
anc[parent]=parent;//初始化自己的lca为自己
for(int i=;i<a[parent].size();i++)
{
LCA(a[parent][i]);
Union(parent,a[parent][i]);
anc[find(parent)]=parent;//把自己和自己子孙们的lca赋值为它
}
f[parent]=;
if(st==parent&&f[end]==)
{
printf("%d\n",anc[find(end)]);
return;
}
if(end==parent&&f[st]==)
{
printf("%d\n",anc[find(st)]);
return;
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(f,,sizeof(f));
memset(a,,sizeof(a));
init();
scanf("%d%d",&st,&end);
for(int i=;i<=n;i++)
if(root[i])
LCA(i);
}
return ;
}
poj 1330 LCA (倍增+离线Tarjan)的更多相关文章
- POJ 1330 LCA裸题~
POJ 1330 Description A rooted tree is a well-known data structure in computer science and engineerin ...
- POJ 1330 LCA最近公共祖先 离线tarjan算法
题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...
- POJ 1330 Nearest Common Ancestors(Tarjan离线LCA)
Description A rooted tree is a well-known data structure in computer science and engineering. An exa ...
- poj 1986 Distance Queries(LCA:倍增/离线)
计算树上的路径长度.input要去查poj 1984. 任意建一棵树,利用树形结构,将问题转化为u,v,lca(u,v)三个点到根的距离.输出d[u]+d[v]-2*d[lca(u,v)]. 倍增求解 ...
- POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)
Closest Common Ancestors Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 13372 Accept ...
- LCA/在线(倍增)离线(Tarjan)
概念 祖先 公共祖先 最近公共祖先 方法1:暴力爬山法 方法2:倍增 求公共祖先 求俩点的距离 Tarjan 概念 祖先 有根树中,一个节点到根的路径上的所有节点被视为这个点的祖先,包括根和它本身 公 ...
- poj 1330 LCA最近公共祖先
今天学LCA,先照一个模板学习代码,给一个离线算法,主要方法是并查集加上递归思想. 再搞,第一个离线算法是比较常用了,基本离线都用这种方法了,复杂度O(n+q).通过递归思想和并查集来寻找最近公共祖先 ...
- LCA:倍增与tarjan
学了好久(一两个星期)都没彻底搞懂的lca,今天总算理解了.就来和大家分享下我自己的心得 首先,如果你还不懂什么是lca,出门左转自行百度 首先讲倍增 倍增的思想很简单,首先进行预处理,用一个深搜将每 ...
- poj 1330 LCA
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #i ...
随机推荐
- /proc/sys/net/ipv4/ip_forward
ip地址分公有地址和私有地址,public address是由INIC(internet network information center)负责,这些ip地址分配给注册并向INIC提出申请的组织机 ...
- JavaScript的组成—ECMAScript、BOM和DOM
JavaScript 是一种基于 ECMAScript 规范的脚本语言,并在此基础上进行了自己的封装.ECMAScript 不是一种编程语言,仅仅是一种脚本语言规范,由欧洲计算机协会制定和发布,任 ...
- const 笔记
.指向const的指针例如:double a=1.01;const double * b=&a;*b=2.1; //这显然是错误的a=2.1; //这是正确的,a和*b的值都会变成2.01,有 ...
- Expert Shell Scripting
Expert Shell Scripting 好好学习这本书
- BZOJ 2423 最长公共子序列
Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0, ...
- MIT教授将网页开发整合为完整独立的程式语言Ur/Web
MIT 的软体技术教授 Adam Chlipala 设计了新的 Ur/Web 程式语言,这是一个整合 HTML.CSS.XML.SQL 及 JavaScript 等网路标准的“完整独立”语言,强调快速 ...
- GCD - Extreme (II)
uva11424: 题目:给出n,求gcd(1,2)+gcd(1,3)+gcd(2,3)+gcd(1,4)+gcd(2,4)+gcd(3,4)+...+gcd(1,n)+gcd(2,n)+...+gc ...
- Apache HTTP Server mod_dav.c 拒绝服务漏洞(CVE-2013-1896)
漏洞版本: Apache HTTP Server < 2.2.25 漏洞描述: CVE ID:CVE-2013-1896 Apache HTTP Server是一款流行的WEB服务器 Apach ...
- POJ 2594 Treasure Exploration(带交叉路的最小路径覆盖)
题意: 派机器人去火星寻宝,给出一个无环的有向图,机器人可以降落在任何一个点上,再沿着路去其他点探索,我们的任务是计算至少派多少机器人就可以访问到所有的点.有的点可以重复去. 输入数据: 首先是n和 ...
- 动态规划(斜率优化):[CEOI2004]锯木厂选址
锯木场选址(CEOI2004) 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来.为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂. 木材只能按照一个方向运输:朝山下运.山脚下有 ...