一.查询一组的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. Android环境搭建及Ionic打包(win7)

    本人刚刚接触Ionic3,初步进行打包操作,将其遇到的问题和整个流程记录下载,方便以后的巩固,也为小白们提供一个参考.因本人没有appleヽ(ー_ー)ノ,而且使用的是WIN7系统,所以暂时只提供了WI ...

  2. 四、spring成长之路——springIOC容器(下)

    目录 5.spring注解开发(Spring扩展知识) 5.1定义配置类:@Configuration 声明一个类为IOC容器 @Bean定义一个Bean 5.2.按照条件进行注入 5.3.@Impo ...

  3. PHP实现验证码功能

    原文链接:http://www.qqdeveloper.com/a/54.html 什么是验证码? 借用百度的解释:验证码这个词最早是在2002年由卡内基梅隆大学的路易斯·冯·安.Manuel Blu ...

  4. Bugku Crack it

    知识点:kali  john工具 不知道hashcat怎么样 一. 用winhex打开 发现右边有root:等信息,想到了linux系统,看了别人的wp,kali中有一个工具john可以破解密码 二. ...

  5. 07-容器类Widget

    容器类Widget 容器类Widget一般只是包装其子Widget,对其添加一些修饰(补白或背景色等).变换(旋转或剪裁等).或限制(大小等) Padding Padding可以给其子节点添加补白(填 ...

  6. lncRNA芯片重注释

    .caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table ...

  7. 20155218 2006-2007-2 《Java程序设计》第3周学习总结

    20155218 2006-2007-2 <Java程序设计>第3周学习总结 教材学习内容总结 ==使用在比较两个参考名称是否参考同一对象:equals()比较实质是否相同. 看见new关 ...

  8. echarts设置小图标位置

    // <!-- 左上角小图标 --> toolbox: { show : true, // orient: 'horizontal', // 布局方式,默认为水平布局,可选为: // // ...

  9. C# Disable CTRL-ALT-DEL, ALT-TAB, ALT-F4, Start Menu and so on…

    使用C#禁用系统的某些特定按键 原文地址:http://www.tamas.io/c-disable-ctrl-alt-del-alt-tab-alt-f4-start-menu-and-so-on/ ...

  10. Dlib简介及在windows7 vs2013编译过程

    Dlib是一个C++库,包含了许多机器学习算法.它是跨平台的,可以应用在Windows.Linux.Mac.embedded devices.mobile phones等.它的License是Boos ...