一.查询一组的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. transform动画的一个3D的正方体盒子

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. less的编译

    less其实也文本类型,跟txt的性质差不多 less有自己语法(变量,函数,作用域.Mixin混入),使css样式更加方便,有逻辑性,提高可维护性,减少重复性代码的冗余. 把less编译成css文件 ...

  3. KKT原理以及SVM数学的理论推导分析

    一直很好奇机器学习实战中的SVM优化部分的数学运算式是如何得出的,如何转化成了含有内积的运算式,今天上了一节课有了让我很深的启发,也明白了数学表达式推导的全过程. 对于一个SVM问题,优化的关键在于 ...

  4. hadoop docker集群搭建

    获取镜像 #本机内 docker pull ubuntu:16.04 编排镜像 启动一个容器 #本机内 docker run -i -t --name master ubuntu:16.04 在容器内 ...

  5. golang 错误处理与异常

    原文地址 golang 中的错误处理的哲学和 C 语言一样,函数通过返回错误类型(error)或者 bool 类型(不需要区分多种错误状态时)表明函数的执行结果,调用检查返回的错误类型值是否是 nil ...

  6. http缓存机制与原理

    一.浏览器缓存分类:强制缓存和协商缓存 二.浏览器加载一个页面的简单流程 浏览器第一次请求 浏览器再次请求页面 三.http缓存涉及到的相关术语 缓存命中率:从缓存中得到数据的请求数与所有请求数的比率 ...

  7. R语言学习笔记(二十四):plyr包的用法

    plyr 这个包,提供了一组规范的数据结构转换形式. Input/Output list data frame array list llply() ldply() laply() data fram ...

  8. 纪中OJ 2019.02.15【NOIP提高组】模拟 B 组 梦回三国 比赛题解(第一个)

    声明 旁边的同学小 H(胡)对我说: “哟,比赛拿了 140,强!要知道,如果哥第三题 AC 了,哥就 230 了,你个废柴!!!(比赛实际分数 130 额呵)” 顿时,千万草泥马从我心中奔腾而过:你 ...

  9. pentestbox更新msf

    pentestbox成功升级msf 1.  输入 msfupdate 进行软件更新 2.  在[*] Updating gems...,软件报错,提示找不到文件路径,输入以下两条命令,尝试单独安装 g ...

  10. adb的配置

    http://jingyan.baidu.com/article/2fb0ba405e815f00f2ec5f9e.html 1. 用快捷键Ctrl + Alt + T 打开终端命令工具,电脑不要插入 ...