LCA近期公共祖先

该分析转之:http://kmplayer.iteye.com/blog/604518

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 <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std; const int MAXN = 100000 + 10;
int degree[MAXN];
bool vst[MAXN];
int ancestor[MAXN];
int f[MAXN];
int rank[MAXN];
vector<int> tree[MAXN];
vector<int> 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;
}

LCA近期公共祖先的更多相关文章

  1. LCA 近期公共祖先 小结

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

  2. 连通分量模板:tarjan: 求割点 &amp;&amp; 桥 &amp;&amp; 缩点 &amp;&amp; 强连通分量 &amp;&amp; 双连通分量 &amp;&amp; LCA(近期公共祖先)

    PS:摘自一不知名的来自大神. 1.割点:若删掉某点后.原连通图分裂为多个子图.则称该点为割点. 2.割点集合:在一个无向连通图中,假设有一个顶点集合,删除这个顶点集合,以及这个集合中全部顶点相关联的 ...

  3. POJ 1470 Closest Common Ancestors【近期公共祖先LCA】

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013912596/article/details/35311489 题目链接:http://poj ...

  4. 近期公共祖先(LCA)——离线Tarjan算法+并查集优化

    一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...

  5. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

  6. POJ1330Nearest Common Ancestors——近期公共祖先(离线Tarjan)

    http://poj.org/problem? id=1330 给一个有根树,一个查询节点(u,v)的近期公共祖先 836K 16MS #include<iostream> #includ ...

  7. LintCode 近期公共祖先

    中等 近期公共祖先 查看执行结果 34% 通过 给定一棵二叉树,找到两个节点的近期公共父节点(LCA). 近期公共祖先是两个节点的公共的祖先节点且具有最大深度. 您在真实的面试中是否遇到过这个题? Y ...

  8. lca 最近公共祖先

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

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

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

随机推荐

  1. Adapter 适配器模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. 11个JavaScript颜色选择器插件

    几年前,很难找到一个合适的颜色选择器.正好看到很多不错的JavaScript颜色选择器插件,故而把这些编译汇总.在本文,Web设计师和开发人员 Kevin Liew 选取了11个相应插件,有些会比较复 ...

  3. Mac下如何进行端口转发,方便一系列需要使用80端口进行的调试工作

    上篇文章介绍到,可以在本地hosts文件中添加一条记录将微信公众号中的可信域名解析道本地127.0.0.1,但tomcat在Mac下非root权限80端口是启动不了的,所以我们可以利用pfctl端口转 ...

  4. 自定义cas客户端核心过滤器AuthenticationFilter

    关于cas客户端的基本配置这里就不多说了,不清楚的可以参考上一篇博文:配置简单cas客户端.这里是关于cas客户端实现动态配置认证需要开发说明. 往往业务系统中有些模块或功能是可以不需要登录就可以访问 ...

  5. spring mvc实现登录验证码

    一.实现图形验证码的基础类 VerifyCodeUtils.java,这个类是从网上摘抄的~ package com.comp.common; import java.awt.Color; impor ...

  6. JavaScript 之 对象和数组

    一:对象   说起对象,我们不自然就想起了面向对象中自封装的一个类,同样JS中也是遵循这个守则,在web编程中几乎天天用到的就是JSON.是的,这就是一个对象,不过这个对象下面的字段都是字符串和值类型 ...

  7. 算法笔记_182:历届试题 核桃的数量(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 小张是软件项目经理,他带领3个开发组.工期紧,今天都在加班呢.为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑).他的要求是: 1. ...

  8. tomcat启用压缩的方式

    <Connector port="7070" protocol="HTTP/1.1"connectionTimeout="20000" ...

  9. LeetCode 37 Count and Say

    The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21, 1211, 111221 ...

  10. 配置zip版本的Tomcat启动

    1.配置jdk 2.CATALINA_HOME=c:\tomcat CATALINA_BASE=c:\tomcat 3.classpath=%CATALINA_HOME%\common\lib\ser ...