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. 二、Silverlight中使用MVVM(二)——提高

    在第一篇文章中的示例中,我们已经简单的了解了应用MVVM模式的流程,我的本意是你已经了解了一点MVVM的概念,然后又没有一个较好的例子学习,可以跟着我一起学习MVVM模式,所以这个部分,都是没有理论知 ...

  2. 一张图帮你看懂 iPhone 6 Plus 的屏幕分辨率

    一张图帮你看懂 iPhone 6 Plus 的屏幕分辨率 几天前公布的 iPhone 6 Plus 官方标称屏幕是 1920 x 1080 的,可是在 Xcode 中我们发现模拟器的屏幕事实上是看似奇 ...

  3. php nginx超时出错

    执行PHP操作大文件insert mysql数据库时,出现这个错误提示 The page you are looking for is temporarily unavailable.Please t ...

  4. javascript调试常用工具讲解

    .Console命令详解,让调试js代码变得更简单 2.<Firebug入门指南>

  5. XMPP协议概述

    XMPP(Extensible Messaging and Presence Protocol,前称Jabber)是一种以 XML 为基础的开放式实时通信协议,关于它的协议细节,网上已经有太多分析文章 ...

  6. JavaScript -- 没事看看

    @.delete 原文:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete

  7. 多媒体开发之rtp打包---打包中的FU-A分包方式说明

    继上篇rtp中的时间戳和负载类型之后,升入到了nalu的分片打包问题,这里做下笔记 (1)fu-a的打包格式 1.基于RTP协议的打包及解包 (1)单个NAL打包 H.264NALU单元常由[star ...

  8. OCR光学字符识别--STN-OCR 测试

    1.同文章中建议的使用ubuntu-python隔离环境,真的很好用 参照:http://blog.topspeedsnail.com/archives/5618启动虚拟环境:source env/b ...

  9. linux安装mongodb,设为全局和后台启动

    curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.5.tgz # 下载 tar -zxvf mongodb-linux ...

  10. mongoDB多级子文档查询

    db.getCollection('product').find({'coverage':{'$elemMatch':{'plan':{'$elemMatch':{'iscoverage':{'$in ...