博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LCA近期公共祖先
阅读量:6632 次
发布时间:2019-06-25

本文共 2033 字,大约阅读时间需要 6 分钟。

                                                                               LCA近期公共祖先 

 

该分析转之:

 

1,并查集+dfs

对整个树进行深度优先遍历。并在遍历的过程中不断地把一些眼下可能查询到的而且结果同样的节点用并查集合并.
2,分类。使每一个结点都落到某个类中,到时候仅仅要运行集合查询,就能够知道结点的LCA了。
对于一个结点u.类别有:
以u为根的子树、除类一以外的以f(u)为根的子树、除前两类以外的以f(f(u))为根的子树、除前三类以外的以f(f(f(u)))为根的子树……
类一的LCA为u,类二为f(u),类三为f(f(u)),类四为f(f(f(u)))。这种分类看起来好像并不困难。

但关键是查询是二维的。并没有一个确定的u。接下来就是这个算法的巧妙之处了。
利用递归的LCA过程。
当lca(u)运行完成后,以u为根的子树已经所有并为了一个集合。而一个lca的内部实际上做了的事就是对其子结点。依此调用lca.
当v1(第一个子结点)被lca。正在处理v2的时候,以v1为根的子树+u同在一个集合里。f(u)+编号比u小的u的兄弟的子树 同在一个集合里,f(f(u)) + 编号比f(u)小的 f(u)的兄弟 的子树 同在一个集合里…… 
而这些集合,对于v2的LCA都是不同的。

因此仅仅要查询x在哪一个集合里,就能知道LCA(v2,x)

另一种可能。x不在不论什么集合里。当他是v2的儿子,v3,v4等子树或编号比u大的u的兄弟的子树(等等)时。就会发生这样的情况。即还没有被处理。

还没有处理过的怎么办?把一个查询(x1,x2)往查询列表里加入两次,一次加入到x1的列表里,一次加入到x2的列表里,假设在做x1的时候发现 x2已经被处理了。那就接受这个询问。(两次中必然仅仅有一次询问被接受).

#include 
#include
#include
#include
#include
using namespace std;const int MAXN = 100000 + 10;int degree[MAXN];bool vst[MAXN];int ancestor[MAXN];int f[MAXN];int rank[MAXN];vector
tree[MAXN];vector
Qes[MAXN];int N;void init(){ for(int i = 0;i <= N;++i){ degree[i] = 0; vst[i] = false; ancestor[i] = -1; f[i] = i; rank[i] = 0; tree[i].clear(); Qes[i].clear(); }}int find(int x){ if(x == f[x]) return x; return f[x] = find(f[x]);}void setUnion(int u,int v){ int a = find(u),b = find(v); if(a != b){ if(rank[a] < rank[b]){ f[a] = b; } else { f[b] = a; if(rank[a] == rank[b]) rank[a]++; } }}void LCA(int u){ ancestor[u] = u; int sz = tree[u].size(); for(int i = 0;i < sz;++i){ LCA(tree[u][i]); setUnion(u,tree[u][i]); ancestor[find(u)] = u; } vst[u] = 1; sz = Qes[u].size(); for(int i = 0;i < sz;++i){ if(vst[Qes[u][i]]){ printf("%d\n",ancestor[find(Qes[u][i])]); return; } }}int main(){ int T; scanf("%d",&T); while(T--){ int x,y; scanf("%d",&N); init(); for(int i = 1;i < N;++i){ scanf("%d%d",&x,&y); degree[y]++; tree[x].push_back(y); } int s,t; scanf("%d%d",&s,&t); Qes[s].push_back(t); Qes[t].push_back(s); for(int i = 1;i <= N;++i){ if(degree[i] == 0){ LCA(i); break; } } } return 0;}

 

 

转载地址:http://ibbvo.baihongyu.com/

你可能感兴趣的文章
Flash AS3 Loader的一些总结
查看>>
js的逻辑 OR 运算符- ||
查看>>
[SQL Server]一次执行资料夹内的.sql 指令码
查看>>
【计算机视觉】粒子滤波跟踪
查看>>
hadoop集群扩展
查看>>
操作系统诊断
查看>>
[Compose] 19. Leapfrogging types with Traversable
查看>>
Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules
查看>>
2015年度新增开源软件排名TOP100
查看>>
BZOJ 2456: mode(新生必做的水题)
查看>>
View State
查看>>
自旋锁spinlock解析
查看>>
【java.lang.UnsupportedClassVersionError】版本不一致出错
查看>>
html5播放mp4视频代码
查看>>
032_nginx配置文件安全下载
查看>>
Linux下tomcat修改成的80端口无法访问
查看>>
为了好好看球,学霸们用深度学习重建整个比赛3D全息图
查看>>
CentOS双机中Docker下安装Mysql并配置互为主从模式
查看>>
sql in not in 案例用 exists not exists 代替
查看>>
WEB前端资源代码:学习篇
查看>>