tarjan求lca的神奇
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
4
4
1
4
4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
~~~~~~~~~~~~~~~华丽的分割线~~~~~~~~~~~~~~~
对于此题,常规解法就是暴力。
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
炸死你。
倍增,可以有效降低复杂度,我也是学了两次之后掌握了它。
这里,我想记录下不久前学习的tarjan求lca
(tarjan真是好东西)
说它是tarjan,其实给我的感觉就是套了一个tarjan的名字罢了。(类似我的dijksPA)其实它就是一个dfs的神奇过程。
先放代码再说
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int n,m,p;
struct edge
{
int next,to,lca;
}e[maxn<<],e1[maxn<<];
int head[maxn<<],cnt,head1[maxn<<];
inline int addedge(int from,int to)//前向星存图
{
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
inline int add (int from,int to)//前向星存储查询
{
e1[++cnt].next=head1[from];
e1[cnt].to=to;
head1[from]=cnt;
}
int f[maxn<<],vis[maxn<<];
int find(int x)//并查集找爹函数
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int tarjan(int u)//神奇的dfs
{
f[u]=u;//爸爸
vis[u]=;//走过
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
tarjan(v);
f[v]=u;//爹
}
}
for(int i=head1[u];i;i=e1[i].next)//询问的图
{
int v=e1[i].to;
if(vis[v])
{
e1[i].lca=find(v);
if(i%==)
e1[i+].lca=e1[i].lca;//
else
e1[i-].lca=e1[i].lca;
}
}
} int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
for(int i=;i<=n;i++)
f[i]=i;//初始化并查集
cnt=;//因为上面村边用过cnt,所以把它拍成0
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
tarjan(p);//从根节点开始dfs
for(int i=;i<=m;i++)
{
printf("%d\n",e1[i*].lca);
}
return ;
}
1.任选一个点为根节点,从根节点开始。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,返回2,否则下一步。
4.合并v到u上。
5.寻找与当前点u有询问关系的点v。
6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
https://www.cnblogs.com/JVxie/p/4854719.html这位大佬的模拟过程真的很强
总的来说,感觉这个算法不是太常用吧。大数据的情况下可能没有倍增快,码量也没小到那里去,而且到现在我还是懵懵的。
写个博客记录一下吧。
最新文章
- Lucene.net站内搜索—3、最简单搜索引擎代码
- URAL 1117. Hierarchy(DP)
- 微软发布手机版 Sample Browser。7000多示例代码一手掌握
- unity3d camera.culling mask
- Bootstrap——Jumbotron编写
- 为什么 Node.js 这么火,而同样异步模式 Python 框架 Twisted 却十几年一直不温不火?
- Allegro16.3约束设置
- 32位和64位dll判断
- Java使用wkhtmltox实现HTML代码生成PDF文档或者图片
- 高性能MySql进化论(十一):常见查询语句的优化
- Bootstrap学习笔记(未整理)
- SLC和MLC闪存芯片的区别
- c#XML配置文件辅助类
- ubuntu 学习笔记1--安装jdk
- Spring 自定义注解,配置简单日志注解
- Android之RecyclerView入门
- 201521123052《Java程序设计》第1周学习总结
- Scala 运算符和集合转换操作示例
- Linux网络协议栈(一)——Socket入门(2)
- python中impyla包报&#39;TSocket&#39; object has no attribute &#39;isOpen&#39;错误
热门文章
- 设计模式----创建型型模式之单件模式(Singleton pattern)
- 使用jsr303实现数据校验
- 常用注解@Controller、@Service、@Autowired
- css浮动产生和清除浮动的几种方式
- 【USACO 5.3.1】量取牛奶
- Fiddle弱网测试
- PHP 调试脚本
- [Luogu3932] 浮游大陆的68号岛
- spark上 spark-shell和java -jar访问hdfs路径问题
- Python网络爬虫——Appuim+夜神模拟器爬取得到APP课程数据