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 ...
随机推荐
- MySQL zip版安装配置
文章出处:http://www.cnblogs.com/winstic/,请保留此连接 这段时间在学习Python 数据库操作知识,简单整理MySQL zip文件安装方法 下载 在MySQL官网htt ...
- Java高精度学习第三弹——ACM中使用JAVA的详细介绍
Chapter I. Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点: (1) 最明显的好处是,学会Java,可以参加Java Challenge . (2) 对于熟悉C/ ...
- Linux 查看 80 端口的占用情况
lsof -i:端口号 eg: lsof -i:80 lsof -i:21 [root@localhost ~]# lsof -i: COMMAND PID USER FD TYPE DEVICE S ...
- 常用 Linux 命令
Check page size: getconf PAGESIZE Check memory information: cat /proc/meminfo Check number of hugepa ...
- C#中&与&&的区别
刚刚翻书发现这个问题,在网上找了一下,我的理解吧. 他俩的区别就是“&”和“|”不执行短路计算,而&&和||执行了短路计算. &不执行短路计算 ——————表达式A&a ...
- SharePoint Designer cannot open site error " the server could not complete your request"
3.SPD cannot open site, in the log :Error when open web service: System.InvalidOperationException: A ...
- Dollars
uva147: 题意:给你几种钱币,在给你一个钱的数目,问有多少种用这些钱来组成这个数目. 题解:完全背包,不过此时要把钱的数目*100,因为是小数,背包的容量都是整数,然后dp,求出每个容量的数目即 ...
- bzoj3438
很容易想到是最小割模型首先对于一个点i,从s到i连一条容量为ai的边,再从i连一条容量为bi的边到t然后就是处理附加权的问题了一开始受到之前的思维定势的影响,一直在思考怎么在作物之间连边由于每种额外收 ...
- osg
智能指针使用: osg::Geode* geode=new osg::Geode;//新建Geode指针 osg::ref_ptr<osg::Geode>geodePtr=geode;// ...
- bzoj 1191 [HNOI2006]超级英雄Hero(最大基数匹配)
1191: [HNOI2006]超级英雄Hero Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2813 Solved: 1331[Submit][ ...