poj 1330 LCA最近公共祖先
今天学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最近公共祖先的更多相关文章
- POJ 1330 LCA最近公共祖先 离线tarjan算法
题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...
- 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 ...
- lca 最近公共祖先
http://poj.org/problem?id=1330 #include<cstdio> #include<cstring> #include<algorithm& ...
- LCA 近期公共祖先 小结
LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- LCA(最近公共祖先)模板
Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...
- CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )
CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...
- LCA近期公共祖先
LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...
- LCA 最近公共祖先 tarjan离线 总结 结合3个例题
在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...
随机推荐
- Hibernate学习总汇
Hibernate的基础知识 什么是框架? 什么是Hibernate框架? |--1.应用在javaee三层结构中的dao层 |--2.在dao层里面做对数据库进行crud操作,使用hibernate ...
- Hibernate与 MyBatis的比较(转)
第一章 Hibernate与MyBatis Hibernate 是当前最流行的O/R mapping框架,它出身于sf.NET,现在已经成为Jboss的一部分. Mybatis 是另外一种优秀 ...
- Unicode 与 Unicode Transformation Format(UTF,UTF-8 / UTF-16 / UTF-32)
ASCII(American Standard Code for Information Interchange):早期它使用7 bits来表示一个字符,总共表示27 = 128个字符:后来扩展到8 ...
- Mybatis 调用存储过程,使用Map进行输入输出参数的传递
做个记录,以备后用 java代码: public String texuChange() throws Exception { try { ...
- vcruntime140.dll丢失解决
之前安装好apache2.4后,打开突然报这样的错误,所以百度一下,发现了问题所在,原因是系统需要安装一个插件,才能正常运行apache2.4 Microsoft Visual C++ 2005 Re ...
- 米扑代理示例(mimvp-proxy-demo)
米扑代理示例(mimvp-proxy-demo) 米扑代理示例(mimvp-proxy-demo)聚合了多种编程语言使用代理IP,由北京米扑科技有限公司(mimvp.com)原创分享. 米扑代理示例, ...
- [js高手之路] vue系列教程 - 组件定义与使用上部(7)
组件是vue框架比较核心的内容,那么什么是组件呢? 通俗点讲:组件是由一堆html, css, javascript组成的代码片段, 作用是为了实现模块的重用 组件的基本用法: <div id= ...
- 移动端为何不使用click而模拟tap事件及解决方案
移动端click会遇到2个问题,click会有200-300ms的延迟,同时click事件的延迟响应,会出现穿透,即点击会触发非当前层的点击事件. 为什么会存在延迟? Google开发者文档中有提到: ...
- 【物联网云端对接-2】通过MQTT协议与阿里云物联网套件进行云端通信
在<程序员>杂志2017.4刊上,曾写过一篇<微软百度阿里三大物联网平台探析>,上面曾介绍了阿里云物联网套件的一些内容,在写该篇文章的时候,凌霄物联网网关还无法对接到此平台( ...
- exit()与_exit()的区别(转)
http://blog.csdn.net/lwj103862095/article/details/8640037 从图中可以看出,_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间, ...