/*
先来个倍增
*/
#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)的更多相关文章

  1. POJ 1330 LCA裸题~

    POJ 1330 Description A rooted tree is a well-known data structure in computer science and engineerin ...

  2. POJ 1330 LCA最近公共祖先 离线tarjan算法

    题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...

  3. POJ 1330 Nearest Common Ancestors(Tarjan离线LCA)

    Description A rooted tree is a well-known data structure in computer science and engineering. An exa ...

  4. poj 1986 Distance Queries(LCA:倍增/离线)

    计算树上的路径长度.input要去查poj 1984. 任意建一棵树,利用树形结构,将问题转化为u,v,lca(u,v)三个点到根的距离.输出d[u]+d[v]-2*d[lca(u,v)]. 倍增求解 ...

  5. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

  6. LCA/在线(倍增)离线(Tarjan)

    概念 祖先 公共祖先 最近公共祖先 方法1:暴力爬山法 方法2:倍增 求公共祖先 求俩点的距离 Tarjan 概念 祖先 有根树中,一个节点到根的路径上的所有节点被视为这个点的祖先,包括根和它本身 公 ...

  7. poj 1330 LCA最近公共祖先

    今天学LCA,先照一个模板学习代码,给一个离线算法,主要方法是并查集加上递归思想. 再搞,第一个离线算法是比较常用了,基本离线都用这种方法了,复杂度O(n+q).通过递归思想和并查集来寻找最近公共祖先 ...

  8. LCA:倍增与tarjan

    学了好久(一两个星期)都没彻底搞懂的lca,今天总算理解了.就来和大家分享下我自己的心得 首先,如果你还不懂什么是lca,出门左转自行百度 首先讲倍增 倍增的思想很简单,首先进行预处理,用一个深搜将每 ...

  9. poj 1330 LCA

    #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #i ...

随机推荐

  1. C语言陷阱——类型转换

    以下例子取自<深入理解计算机系统>. 考虑如下的C语言代码: #include<stdio.h> typedef unsigned char* byte_pointer; vo ...

  2. Gray码 (格雷码) 【二进制】

    以下内容是看了Matrix67的关于二进制的blog(Link)的一点总结与摘录. Gray码,中文“格雷码”,是一种特殊的编码,相邻两个格雷码的二进制表示中有且仅有一位不同,且 n 阶 Gray 码 ...

  3. 物联网传输协议MQTT

    MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务.MQTT是专门针对物联网开发的轻量级传输协议.MQTT协议针对低 ...

  4. Preparing for the Contest

     Codeforces Round #222 (Div. 1)B:http://codeforces.com/contest/377/problem/B 题意:m个任务,每个任务会有一个复杂度,然后给 ...

  5. City Game

    hdu1505:http://acm.hdu.edu.cn/showproblem.php?pid=1505 题解:给你一个字符矩阵,里面有R和F两种字符,然后让你找一个最大的子矩阵,这个最大的子矩阵 ...

  6. struts2令牌,防止重复提交

    struts2的令牌,可以用来防止重复提交,其原理是在提交jsp页面中,写入一个隐藏域name="token",然后在action中定义一个变量token并get.set.在服务器 ...

  7. ASP.NET服务器推送及前后台实时交互

    一:项目需求 页面需要做一个上传Excel功能,并处理Excel中的数据到数据库中 这是一个较为漫长的过程 这时我需要在页面上显示处理进度的提示,给用户一个良好的体验 比如给用户提示“正在上传文档”, ...

  8. 【HDOJ】2717 Catch That Cow

    bfs. /* 2717 */ #include <iostream> #include <cstdio> #include <cstring> #include ...

  9. Effective c++ 第一章 让自己习惯C++

    条款 01:c++是一个语言联邦而不是一种单一的语言, 它包括: 1.C语言:没有模版.没有异常.没有重载…… 2.Object-Oriented C++:class.析构函数.构造函数.封装.继承. ...

  10. bzoj3531

    不难想到树链剖分这题的难点是记录的是路径上宗教相同的点裸的想法是对每一种宗教都开一棵线段树,记录每个点的评级但显然这样会爆空间,仔细分析一下,这些线段树内很多点压根就没用到因此我们考虑对线段树动态开点 ...