一.查询一组的LCA

Nearest Common Ancestors

A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:



In the figure, each node is labeled with an integer from {1,
2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node
y if node x is in the path between the root and node y. For example,
node 4 is an ancestor of node 16. Node 10 is also an ancestor of node
16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of
node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6,
and 7 are the ancestors of node 7. A node x is called a common ancestor
of two different nodes y and z if node x is an ancestor of node y and an
ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of
nodes 16 and 7. A node x is called the nearest common ancestor of nodes y
and z if x is a common ancestor of y and z and nearest to y and z among
their common ancestors. Hence, the nearest common ancestor of nodes 16
and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.

For other examples, the nearest common ancestor of nodes 2
and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node
8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the
last example, if y is an ancestor of z, then the nearest common ancestor
of y and z is y.

Write a program that finds the nearest common ancestor of two distinct nodes in a tree.

Input

The input consists of T test cases. The number of test cases (T)
is given in the first line of the input file. Each test case starts with
a line containing an integer N , the number of nodes in a tree,
2<=N<=10,000. The nodes are labeled with integers 1, 2,..., N.
Each of the next N -1 lines contains a pair of integers that represent
an edge --the first integer is the parent node of the second integer.
Note that a tree with N nodes has exactly N - 1 edges. The last line of
each test case contains two distinct integers whose nearest common
ancestor is to be computed.

Output

Print exactly one line for each test case. The line should contain the integer that is the nearest common ancestor.

Sample Input

2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5

Sample Output

4
3 使用链式前向星存图得到的代码:
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 10010
struct node
{
int to;
int next;
} edge[MAX];
int head[MAX];
int f[MAX];
int vis[MAX];
int is_root[MAX];
int n;
int cnt;
int cx,cy;
int ans;
int Find(int x)
{
if(x!=f[x])
f[x]=Find(f[x]);
return f[x];
} void Join(int x,int y)///合并集合
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
{
f[fy]=fx;
}
} void add_edge(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
} void LCA(int u)
{
int i,v;
for(i=head[u]; i!=-; i=edge[i].next)
{
v=edge[i].to;
LCA(v);
Join(u,v);
vis[v]=;
}
if(cx==u&&vis[cy]==)
{
ans=Find(cy);
}
if(cy==u&&vis[cx]==)
{
ans=Find(cx);
}
}
int main()
{
int T,i;
int root;
scanf("%d",&T);
while(T--)
{ memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(is_root,,sizeof(is_root));
scanf("%d",&n);
cnt=;
for(i=; i<=n; i++)
f[i]=i;
for(i=; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
is_root[y]=;
}
for(i=; i<=n; i++)///找根节点
{
if(is_root[i]==)///入度为0的则是根节点
{
root=i;
}
}
scanf("%d%d",&cx,&cy);///单组查询
LCA(root);
printf("%d\n",ans);
}
return ;
}

二.查询多组的LCA

Closest Common Ancestors

Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)

Input

The data set, which is read from a the std input, starts with the tree description, in the form:

nr_of_vertices

vertex:(nr_of_successors) successor1 successor2 ... successorn

...

where vertices are represented as integers from 1 to n ( n
<= 900 ). The tree description is followed by a list of pairs of
vertices, in the form:

nr_of_pairs

(u v) (x y) ...

The input file contents several data sets (at least one).

Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.

Output

For each common ancestor the program prints the ancestor and the
number of pair for which it is an ancestor. The results are printed on
the standard output on separate lines, in to the ascending order of the
vertices, in the format: ancestor:times

For example, for the following tree:

Sample Input

5
5:(3) 1 4 2
1:(0)
4:(0)
2:(1) 3
3:(0)
6
(1 5) (1 4) (4 2)
(2 3)
(1 3) (4 3)

Sample Output

2:1
5:5

Hint

Huge input, scanf is recommended.
 
这里使用链式前向星存图,又开了一个que数组来记录要查询的两个点存在关系。
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 1010
struct node
{
int to;
int next;
} edge[MAX];
int head[MAX];
int f[MAX];
int vis[MAX];
int is_root[MAX];
int que[MAX][MAX];///新开一个数组记录要查询的两个点
int ans[MAX];
int n;
int cnt;
int cx,cy;
int Find(int x)
{
if(x!=f[x])
f[x]=Find(f[x]);
return f[x];
} void Join(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
{
f[fy]=fx;
}
} void add_edge(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
} void LCA(int u)
{
int i,v;
for(i=head[u]; i!=-; i=edge[i].next)
{
v=edge[i].to;
LCA(v);
Join(u,v);
vis[v]=;
}
for(i=; i<=n; i++)///访问所有与u有关系的点
{
if(vis[i]&&que[u][i])
{
ans[Find(i)]+=que[u][i];
}
}
}
int main()
{
int T,i,j,t;
int root;
int x,y;
int num;
while(scanf("%d",&n)!=EOF)
{
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(is_root,,sizeof(is_root));
memset(que,,sizeof(que));
memset(ans,,sizeof(ans));
cnt=;
for(i=; i<=n; i++)
{
f[i]=i;
}
for(i=; i<=n; i++)
{ scanf("%d:(%d)",&x,&num);
for(j=; j<=num; j++)
{
scanf("%d",&y);
add_edge(x,y);
is_root[y]=;
}
}
scanf("%d",&t);
for(i=; i<=t; i++)
{
scanf(" (%d %d)",&x,&y);
que[x][y]++;
que[y][x]++;
}
for(i=; i<=n; i++)
{
if(is_root[i]==)
{
root=i;
}
}
LCA(root);
for(i=; i<=n; i++)
{
if(ans[i])
{
printf("%d:%d\n",i,ans[i]);
}
}
}
return ;
}

LCA(Tarjan算法)模板的更多相关文章

  1. HDU 2586 ( LCA/tarjan算法模板)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...

  2. [CF 191C]Fools and Roads[LCA Tarjan算法][LCA 与 RMQ问题的转化][LCA ST算法]

    参考: 1. 郭华阳 - 算法合集之<RMQ与LCA问题>. 讲得很清楚! 2. http://www.cnblogs.com/lazycal/archive/2012/08/11/263 ...

  3. Tarjan 算法求 LCA / Tarjan 算法求强连通分量

    [时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...

  4. Tarjan 算法&模板

    Tarjan 算法 一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连 ...

  5. 最近公共祖先LCA(Tarjan算法)的思考和算法实现

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...

  6. POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)

    题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从 ...

  7. LCA:Tarjan算法实现

    本博文转自http://www.cnblogs.com/JVxie/p/4854719.html,转载请注明出处 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有 ...

  8. 最近公共祖先LCA(Tarjan算法)的思考和算法实现——转载自Vendetta Blogs

    LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...

  9. Tarjan算法(模板)

    算法思想: 首先要明确强连通图的概念,一个有向图中,任意两个点互相可以到达:什么是强连通分量?有向图的极大连通子图叫强连通分量. 给一个有向图,我们用Tarjan算法把这个图的子图(在这个子图内,任意 ...

  10. hdu 2586 How far away ?(LCA - Tarjan算法 离线 模板题)

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

随机推荐

  1. 设计一个学生类&班级类

    第一题 设计一个学生类 属性:姓名.学号.年龄.成绩 设计一个班级类要求:实现向班级中添加学生.删除学生.查看学生.按照指定条件排序 属性:班级代号,所有学生 需要使用 calss, __int__, ...

  2. MySql 5.7.21免安装版本win10下的配置

    1.解压到想要安装的位置,创建my.ini文件 my.ini的内容如下 [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [mysqld] #设 ...

  3. JavaWeb开发使用jsp还是html做前端页面

    一.概述 刚开始学习Javaweb开发的小伙伴都有一个疑惑:用jsp开发前端还是用HTML开发前端呢? 这个疑惑的来源主要是:刚接触完前端但又不深入学习js,接着学习jsp,发现老师们都一直用着jsp ...

  4. thinkphp3.2+cropper上传多张图片剪切图片

    实现效果截图 点加号可以继续上传第二张图片 代码部<--引入cropper相关文件--> <link rel="stylesheet" href="/h ...

  5. 树莓派安装samba服务

    1.安装 sudo apt-get update sudo apt-get install samba sudo apt-get install samba-common-bin 2.配置 sudo ...

  6. python学习之简介与环境安装

    [转自]http://www.cnblogs.com/wupeiqi/articles/5433925.html --Python可以应用于众多领域 如:数据分析.组件集成.网络服务.图像处理.数值计 ...

  7. 使用ofstream输出unicode

    void saveWideFileHead(std::ofstream& out)// 写入文件内容前,先写入BOM { char const* const utf16head = " ...

  8. 《Java核心技术36讲》阅读笔记:Exception和Error有什么区别?

    1.Exception 和 Error有什么区别?运行时异常与一般异常有什么区别? Exception和Error都继承自java.lang.Throwable.在Java中只有Throwable的实 ...

  9. 20155323 2016-2017-2 《Java程序设计》第4周学习总结

    20155323 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 继承的目的:继承是为了多态,能够采用父类引用指向子类对象,这样可以让代码更灵活.继承之后可以 ...

  10. 20155330 2016-2017-2 《Java程序设计》第四周学习总结

    20155330 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 学习目标 理解封装.继承.多态的关系 理解抽象类与接口的区别 掌握S.O.L.I.D原则 了 ...