今天学LCA,先照一个模板学习代码,给一个离线算法,主要方法是并查集加上递归思想。

再搞,第一个离线算法是比较常用了,基本离线都用这种方法了,复杂度O(n+q)。通过递归思想和并查集来寻找最近公共祖先,自己模拟下过程就可以理解了。

然后就是在线算法,在线算法方法就很多了,比较常用的是LCA的RMQ转换,然后还有线段树,DP等,最后效率最高的就是倍增法了每次查询O(LogN)

这道题是离线的。

给出离线的Tarjan和倍增算法吧。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define MAXN 10001
int f[MAXN];
int r[MAXN];
int indegree[MAXN];
int vis[MAXN];
vector<int>hash[MAXN],Qes[MAXN];
int ancestor[MAXN];
void init(int n)
{
int i;
for(int i=1;i<=n;i++)
{
r[i]=1;
f[i]=1;
indegree[i]=0;
vis[i]=0;
ancestor[i]=0;
hash[i].clear();
Qes[i].clear();
}
}
int find(int n)
{
if(f[n]!=n)
f[n]=find(f[n]);
return f[n];
} int Union(int x,int y)
{
int a=find(x);
int b=find(y);
if(a==b)
return 0;
else if(r[a]<r[b])
{
f[a]=b;
r[b]+=r[a];
}
else
{
f[b]=a;
r[a]+=r[b];
}
return 1;
}
void LCA(int u)
{
ancestor[u]=u;
int size=hash[u].size();
for(int i=0;i<size;i++)
{
LCA(hash[u][i]);
Union(u,hash[u][i]);
ancestor[find(u)]=u;
}
vis[u]=1;
size=Qes[u].size();
for(int i=0;i<size;i++)
{
if(vis[Qes[u][i]]==1)
{
printf("%d\n",ancestor[find(Qes[u][i])]);
return ;
}
}
} int main()
{
int T,s,t,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init(n);
for(int i=1;i<=n-1;i++)
{ scanf("%d%d",&s,&t);
hash[s].push_back(t);
indegree[t]++;
}
scanf("%d%d",&s,&t);
Qes[s].push_back(t);
Qes[t].push_back(s);
for(int j=1;j<=n;j++)
{
if(indegree[j]==0)
{
LCA(j);
break;
}
}
}
return 0;
}

倍增法:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int N=10002;
const int Log=20;
int dp[N][Log],depth[N],deg[N];
struct Edge
{
int to;
Edge *next;
}edge[2*N],*cur,*head[N];
void addedge(int u,int v)
{
cur->to=v;
cur->next=head[u];
head[u]=cur++;
}
void dfs(int u)
{
depth[u]=depth[dp[u][0]]+1;
for(int i=1;i<Log;i++) dp[u][i]=dp[dp[u][i-1]][i-1];
for(Edge *it=head[u];it;it=it->next)
{
dfs(it->to);
}
}
int lca(int u,int v)
{
if(depth[u]<depth[v])swap(u,v);
for(int st=1<<(Log-1),i=Log-1;i>=0;i--,st>>=1)
{
if(st<=depth[u]-depth[v])
{
u=dp[u][i];
}
}
if(u==v) return u;
for(int i=Log-1;i>=0;i--)
{
if(dp[v][i]!=dp[u][i])
{
v=dp[v][i];
u=dp[u][i];
}
}
return dp[u][0];
}
void init(int n)
{
for(int i=0;i<=n;i++)
{
dp[i][0]=0;
head[i]=NULL;
deg[i]=0;
}
cur=edge;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,u,v;
scanf("%d",&n);
init(n);
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
deg[v]++;
dp[v][0]=u;
}
for(int i=1;i<=n;i++)
{
if(deg[i]==0)
{
dfs(i);
break;
}
}
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return 0;
}

poj 1330 LCA最近公共祖先的更多相关文章

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

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

  2. poj 1330 【最近公共祖先问题+fa[]数组+ 节点层次搜索标记】

    题目地址:http://poj.org/problem?id=1330 Sample Input 2 16 1 14 8 5 10 16 5 9 4 6 8 4 4 10 1 13 6 15 10 1 ...

  3. lca 最近公共祖先

    http://poj.org/problem?id=1330 #include<cstdio> #include<cstring> #include<algorithm& ...

  4. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

  5. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  6. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  7. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  8. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...

  9. LCA 最近公共祖先 tarjan离线 总结 结合3个例题

    在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...

随机推荐

  1. Linux Shell 1 - Print from terminal

    Two ways to print info from terminal - echo & printf - Echo a. Exclamation mark is supported in ...

  2. Numpy 操作

    一.Numpy 属性 # 列表转化为矩阵 In []: arr = np.array([[,,],[,,]]) In []: arr Out[]: array([[, , ], [, , ]]) 1, ...

  3. 求m区间内的最小值

    洛谷P1440 求m区间内的最小值 ............................................................................... 以上 ...

  4. 解决 apache poi 转换 word(docx) 文件到 html 文件表格没边框的问题

    一.起因 这几天在做电子签章问题,要通过替换docx文件中的占位符生成包含业务数据的合同数据,再转换成html文件,转换成pdf文件.遇到的问题是:通过apache poi转换docx到html时,原 ...

  5. Cordova + idea 环境搭建

    1.安装前期工作 1).安装Node.js http://nodejs.cn/download/ 里面内置了npm,可以用来安装 Cordova,把该路径添加到环境变量,这样就可以在 cmd 里面任何 ...

  6. Learn c for the Second day

    十六进制对应的二进制码 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 0       ...

  7. 【SSH】---【Struts2、Hibernate5、Spring4】【SSH框架整合笔记 】

    一.为什么要使用接口? 三层体系架构上层调用下层的时候最好使用接口,比如action层调用service的时候,private IUserDAO userDAO;这里将属性定义为接口,调用DAO的时候 ...

  8. zyUpload---照片上传并显示效果

    demo 下载连接

  9. javascript二维数组排序

    js使用sort()函数对二维数组快速排序的写法 作者:admin    时间:2015-7-3 9:31:4    浏览:1847 js数组的排序方法有很多,冒泡法,插入法等等,不过对于数组的排序来 ...

  10. HTML,CSS,JS之间的关系

    HTML,CSS,JS之间的关系 本笔记是自己在浏览了各位前辈后拼凑总结下来的知识,供自己使用消化.后面会附上各种链接地址,尊重原创 最准确的网页设计思路是把网页分成三个层次,即:结构层(HTML). ...