Closest Common Ancestors
Time Limit: 2000MS   Memory Limit: 10000K
Total Submissions: 18013   Accepted: 5774

Description

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
有向图求LCA,注意输入的处理。
有向图只有一个树根,利用并查集求树根。无向图中可选任意一点作树根,在dfs是比有向图多一个条件,详情见代码。
#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
const int MAXN=;
int V;
vector<int> G[MAXN];
int par[MAXN];
void prep()
{
for(int i=;i<=MAXN;i++)
{
par[i]=i;
}
}
int fnd(int x)
{
if(par[x]==x)
return x;
return par[x]=fnd(par[x]);
}
void unite(int father,int son)
{
par[son]=fnd(father);
}
int fa[MAXN],dep[MAXN];
void dfs(int u,int father,int d)
{
fa[u]=father,dep[u]=d;
for(int i=;i<G[u].size();i++)
dfs(G[u][i],u,d+);//在无向图中 需要加上 if(G[u][i]!=father)
}
int lca[MAXN];
int LCA(int u,int v)
{
while(dep[u]>dep[v]) u=fa[u];
while(dep[v]>dep[u]) v=fa[v];
while(u!=v)
{
u=fa[u];
v=fa[v];
}
return u;
}
int main()
{
while(scanf("%d",&V)!=EOF)
{
for(int i=;i<=V;i++) G[i].clear();
prep();
memset(lca,,sizeof(lca));
for(int i=;i<V;i++)
{
int u,t;
scanf("%d:(%d)",&u,&t);
while(t--)
{
int v;
scanf("%d",&v);
G[u].push_back(v);
unite(u,v);
}
}
int root=fnd();
dfs(root,-,);
int Q;
scanf("%d",&Q);
while(true)
{
char ch=getchar();
if(ch=='(')
{
int u,v;
scanf("%d %d",&u,&v);
int a=LCA(u,v);
lca[a]++;
Q--;
getchar();//不能丢,有开就有闭
}
if(Q==) break;
}
for(int i=;i<=V;i++)
{
if(lca[i]!=) printf("%d:%d\n",i,lca[i]);
}
}
return ;
}

tarjan+并查集离线算法

#include"cstdio"
#include"cstring"
#include"vector"
using namespace std;
const int MAXN=;
int V;
vector<int> G[MAXN];
int que[MAXN][MAXN];
int vis[MAXN];
int par[MAXN];
int cnt[MAXN];
void prep()
{
for(int i=;i<=MAXN;i++)
par[i]=i;
}
int fnd(int x)
{
if(par[x]==x)
return x;
return par[x]=fnd(par[x]);
}
void unite(int father,int son)
{
par[son]=fnd(father);
}
void dfs(int u)
{
for(int i=;i<=V;i++)
if(vis[i]&&que[u][i])
{
int fa=fnd(i);//fa 为u与i的LCA
cnt[fa]+=que[u][i];
}
vis[u]=;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
dfs(v);
unite(u,v);
}
}
int indeg[MAXN];
int main()
{
while(scanf("%d",&V)!=EOF)
{
prep();
for(int i=;i<=V;i++) G[i].clear();
memset(que,,sizeof(que));
memset(vis,,sizeof(vis));
memset(cnt,,sizeof(cnt));
memset(indeg,,sizeof(indeg));
for(int i=;i<V;i++)
{
int u,t;
scanf("%d:(%d)",&u,&t);
while(t--)
{
int v;
scanf("%d",&v);
G[u].push_back(v);
indeg[v]++;
}
}
int Q;
scanf("%d",&Q);
while(Q--)
{
int u,v;
scanf(" (%d %d)",&u,&v);
que[u][v]++;
que[v][u]++;
}
for(int i=;i<=V;i++)
if(!indeg[i])//入度为0的点为根节点
{
dfs(i);
break;
}
for(int i=;i<=V;i++)
if(cnt[i]!=) printf("%d:%d\n",i,cnt[i]);
}
return ;
}

POJ(有向图求LCA)的更多相关文章

  1. POJ 1986:Distance Queries(倍增求LCA)

    http://poj.org/problem?id=1986 题意:给出一棵n个点m条边的树,还有q个询问,求树上两点的距离. 思路:这次学了一下倍增算法求LCA.模板. dp[i][j]代表第i个点 ...

  2. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  3. POJ 1330(LCA/倍增法模板)

    链接:http://poj.org/problem?id=1330 题意:q次询问求两个点u,v的LCA 思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v) AC代码: #inc ...

  4. Tarjan算法离线 求 LCA(最近公共祖先)

    本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig ...

  5. 树链剖分求LCA

    树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...

  6. 树上倍增求LCA(最近公共祖先)

    前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...

  7. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  8. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  9. 【倍增】洛谷P3379 倍增求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

随机推荐

  1. uboot之run_command简单分析

    本文档简单分析了uboot中命令的实现.run_command函数的实现以及从uboot命令行接收并处理命令的过程. 作者: 彭东林 邮箱: pengdonglin137@163.com http:/ ...

  2. 如何将linux服务器作为文件服务器

    在开发过程中想要使用linux服务器作为文件服务器,可以通过 IP+文件名来获取文件信息,比如http://localhost/banner/a.jpg.设置过程如下 1.安装apache2 sudo ...

  3. Tinker 热修复框架 简单上手教程

    当你们看到Tinker的时候是不是有点愣逼这个是什么东西? 简单来说就是不需要重新下载app和重新安装app 来进行更新app的技术框架. 看看这个吧,我也是才学习 ,先做个学习记录 参考:Tinke ...

  4. 图像处理之基础---二维卷积c实现

    http://wenku.baidu.com/link?url=4RzdmvP9sdaaUbnVEW4OyBD-g67wIOiJjKFF3Le_bu7hIiBS7I6hMcDmCXrQwsHvrsPv ...

  5. python 基础 9.2 mysql 事务

    一. mysql 事务    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如,你操作一个数据库,公司的一个员工离职了,你要在数据库中删除它的资料,也要删除该人员相关的,比如邮箱,个人资产等 ...

  6. LA 3882 And Then There Was One[约瑟夫问题的变形]

    And Then There Was One UVALive - 3882 Sample Input   Sample Output //设f[i]为(原约瑟夫问题)第i次要删除的标号 #includ ...

  7. 九度OJ 1060:完数VS盈数 (数字特性)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5590 解决:2093 题目描述: 一个数如果恰好等于它的各因子(该数本身除外)子和,如:6=3+2+1.则称其为"完数" ...

  8. MarkdownPad - The Markdown Editor for Windows http://markdownpad.com/

    MarkdownPad - The Markdown Editor for Windows http://markdownpad.com/

  9. Kaggle系列1:手把手教你用tensorflow建立卷积神经网络实现猫狗图像分类

    去年研一的时候想做kaggle上的一道题目:猫狗分类,但是苦于对卷积神经网络一直没有很好的认识,现在把这篇文章的内容补上去.(部分代码参考网上的,我改变了卷积神经网络的网络结构,其实主要部分我加了一层 ...

  10. centos下安装wordpress

    https://www.jianshu.com/p/2439dc2187b2 https://blog.csdn.net/liuhelong/article/details/79924014