poj 1330 Nearest Common Ancestors(LCA:最近公共祖先)
多校第七场考了一道lca,那么就挑一道水题学习一下吧= =
最简单暴力的方法:建好树后,输入询问的点u,v,先把u全部的祖先标记掉,然后沿着v->rt(根)的顺序检查,第一个被u标记的点即为u,v的公共祖先。
标记的时候又犯老毛病了:while,do while都不对,最后还是while(1)了T^T
#include<cstdio>
#include<cstring> const int MAXN=; int p[MAXN],vis[MAXN]; int main()
{
int T,n,u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(vis,,sizeof(vis));
memset(p,-,sizeof(p));
for(int i=;i<n-;i++){
scanf("%d%d",&u,&v);
p[v]=u;
}
scanf("%d%d",&u,&v);
while()
{
vis[u]=;
if(p[u]==-)
break;
u=p[u];
}
while(vis[v]!=)
v=p[v];
printf("%d\n",v);
}
return ;
}
/*
10
3
1 2
1 3
2 3
*/
然后是tarjin了:
自己先照着推了一遍代码,才把图示给看明白:http://www.csie.ntnu.edu.tw/~u91029/LowestCommonAncestor.html
可以处理多组询问
因为是以dfs为框架,所以先处理子树,依次将当前点u的每棵子树加入当前点的集合,之后对当前点进行询问(u,v)。若v已被标记,由于是dfs,所以最近公共祖先包含v的子树必然已经完成了搜索,那么v所在集合的祖先 find(v) 就是询问(u,v)的解。又因为是dfs,所以子树内的询问必然已经完成。
注意:询问(u,v)要正反向各加一遍,因为标记vis有先后顺序,而我们不清楚u,v的被访问的顺序。搜索到u时v尚未被标记,会放弃此次询问。所以不必担心同一次询问被完成了两次,其中一次会被舍弃。
关键是要理解先处理dfs,再合并集合。
#include<cstdio>
#include<cstring>
#include<vector>
#define clr(a,m) memset(a,m,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std; const int MAXN=; struct Edge{
int v,next;
Edge(){}
Edge(int _v,int _next):v(_v),next(_next){}
}edge[MAXN<<]; vector<int>query[MAXN]; int p[MAXN],vis[MAXN],ancestor[MAXN];
int head[MAXN],tol; void init(int n)
{
tol=;
clr(head,-); rep(i,,n){
query[i].clear();
}
} void add(int u,int v)
{
edge[tol]=Edge(v,head[u]);
head[u]=tol++;
} int build(int n)
{
int u,v;
init(n);
clr(vis,);
rep(i,,n-){
scanf("%d%d",&u,&v);
vis[v]=;
add(u,v);
}
rep(i,,){
scanf("%d%d",&u,&v);
query[u].push_back(v);
query[v].push_back(u);
}
rep(i,,n)
if(!vis[i])
return i;
} int find(int x)
{
return (x==p[x])?x:(p[x]=find(p[x]));
} void dfs(int x)
{
vis[x]=;
for(int i=head[x];i!=-;i=edge[i].next)
{
int v=edge[i].v;
dfs(v);
p[v]=x;
} int siz =query[x].size()-;
rep(i,,siz)
{
if(vis[query[x][i]]){
printf("%d\n",find(query[x][i]));
return ;
}
}
} void LCA(int rt,int n)
{
clr(vis,);
rep(i,,n)
p[i]=i;
dfs(rt);
} int main()
{
int T,n,u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int rt=build(n);
LCA(rt,n);
}
return ;
}
有一点要注意的:query[x].size()的返回值竟然不是 int 型的= = ,不信可以把 siz 省略掉,在循环内打印一下,惊喜的发现 for(int i=0;i<-1;i++) 这种东西竟然能够进入循环。强制转换(int)也能解决。
再附上一段代码,是实现全部询问的,当然不适合这道题,MAXN=11111,MLE我竟然还反应了半天。。
void dfs(int x,int n)
{
vis[x]=;
for(int y=head[x];y!=-;y=edge[y].next)
{
int v=edge[y].v;
dfs(v,n);
p[v]=x;
}
rep(y,,n)
if(vis[y])
lca[x][y]=lca[y][x]=find(y);
}
poj 1330 Nearest Common Ancestors(LCA:最近公共祖先)的更多相关文章
- POJ 1330 Nearest Common Ancestors 【最近公共祖先LCA算法+Tarjan离线算法】
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 20715 Accept ...
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...
- POJ 1330 Nearest Common Ancestors LCA题解
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19728 Accept ...
- poj 1330 Nearest Common Ancestors lca 在线rmq
Nearest Common Ancestors Description A rooted tree is a well-known data structure in computer scienc ...
- poj 1330 Nearest Common Ancestors LCA
题目链接:http://poj.org/problem?id=1330 A rooted tree is a well-known data structure in computer science ...
- POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)
/* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...
- POJ 1330 Nearest Common Ancestors(LCA模板)
给定一棵树求任意两个节点的公共祖先 tarjan离线求LCA思想是,先把所有的查询保存起来,然后dfs一遍树的时候在判断.如果当前节点是要求的两个节点当中的一个,那么再判断另外一个是否已经访问过,如果 ...
- POJ 1470 Closest Common Ancestors(LCA 最近公共祖先)
其实这是一个裸求LCA的题目,我使用的是离线的Tarjan算法,但是这个题的AC对于我来说却很坎坷……首先是RE,我立马想到数组开小了,然后扩大了数组,MLE了……接着把数组调整适当大小,又交了一发, ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- POJ - 1330 Nearest Common Ancestors(基础LCA)
POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %l ...
随机推荐
- POJ 3723 Conscription 最小生成树
题目链接: 题目 Conscription Time Limit: 1000MS Memory Limit: 65536K 问题描述 Windy has a country, and he wants ...
- ORA-01031:insufficient privileges
描述:oracle11g用scott用户在plsql上以sysdba身份登录显示以上错误,可是在cmd面板中却正常,网上各种找答案不没有对症,最后这位网友的回答解决了我的问题. 原帖网址:http:/ ...
- Android SDK下载地址
原地址:http://lameck.blog.163.com/blog/static/38811374201262111309677/ Android SDK.ADT.tools等官方下载地址(201 ...
- 在 tornado 中异步无阻塞的执行耗时任务
在 tornado 中异步无阻塞的执行耗时任务 在 linux 上 tornado 是基于 epoll 的事件驱动框架,在网络事件上是无阻塞的.但是因为 tornado 自身是单线程的,所以如果我们在 ...
- HDOJ 1856 More is better
转自:wutianqi http://www.wutianqi.com/?p=1069 tag:并查集 #include <iostream> using namespace std; # ...
- [shell编程]一个简单的脚本
首先,为什么要学习shell呢?哈哈,当然不是shell能够怎样怎样然后100字. 最近看到一篇博文<开阔自己的视野,勇敢的接触新知识>,读完反思良久.常常感慨自己所会不多,对新知识又有畏 ...
- grunt安装失败处理
1.官网 Grunt官网 http://gruntjs.com 2.前言 前段时间一不小心升级了win10(万恶的360),各种不适应各种问题各种软件bug,最终决定回退到win7,然后悲催的发现系统 ...
- Exceptionin thread "main" java.lang.UnsatisfiedLinkError:org.apache.hadoop.util.NativeCrc32.nativeComputeChunkedSumsByteArray(II[BI[BIILjav
在eclipse上运行hadoop报错:Exceptionin thread "main" java.lang.UnsatisfiedLinkError:org.apache.ha ...
- 【Linux高频命令专题(23)】tar
概述 通过SSH访问服务器,难免会要用到压缩,解压缩,打包,解包等,这时候tar命令就是是必不可少的一个功能强大的工具.linux中最流行的tar是麻雀虽小,五脏俱全,功能强大. tar命令可以为li ...
- Qt4升级Qt5注意问题
Qt4升级Qt5注意问题 Qt4过渡到Qt5的项目一开始就受阻,记录一下遇到的下面的问题 --->编译遇到类似错误: error: QCalendarWidget: No such file o ...