POJ(有向图求LCA)
| Time Limit: 2000MS | Memory Limit: 10000K | |
| Total Submissions: 18013 | Accepted: 5774 |
Description
Input
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 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)的更多相关文章
- POJ 1986:Distance Queries(倍增求LCA)
http://poj.org/problem?id=1986 题意:给出一棵n个点m条边的树,还有q个询问,求树上两点的距离. 思路:这次学了一下倍增算法求LCA.模板. dp[i][j]代表第i个点 ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
- POJ 1330(LCA/倍增法模板)
链接:http://poj.org/problem?id=1330 题意:q次询问求两个点u,v的LCA 思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v) AC代码: #inc ...
- Tarjan算法离线 求 LCA(最近公共祖先)
本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig ...
- 树链剖分求LCA
树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- 【树链剖分】洛谷P3379 树链剖分求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
随机推荐
- ejabberd日志分析客户端登录流程
通过ejabberd的日志,整理了下客户端登录流程. 1. 通过TCP连接5222端口的流程: (1) 客户端向服务器发送stream流 <stream:stream to="nba. ...
- 安装Redis图形监控工具---RedisLive
RedisLive简介 RedisLive是一款用Python编写基于WEB的Redis图形监控工具,也是一款实时监控Redis数据的开源软件,以WEB的形式展现出redis中的key的情况,实例数据 ...
- 前后端分离之fiddler前端开发代理 autoresponder 正则表达式 regex:(?insx) 修正符详解
regex:(?isx)^http://127.0.0.1:3000(/dlscene)?/order/(\w*) http://127.0.0.1:8080/dlscene/order/$2 上面这 ...
- rtsp转rtmp、hls网页直播服务器EasyNVR前端兼容性调试:ie下的 pointer-events- none
发现问题: 之前在做EasyNVR 的web页面开发过程中,力求的都是一个播放效果的.功能的展示.对于兼容性也有注意,但有些细节还是难免有所疏忽. 内部测试发现:由于我们是流媒体的实时视频直播,在we ...
- multiple-value uuid.NewV4() in single-value context
[root@t ~]# go get github.com/aliyun/aliyun-sts-go-sdk/sts# github.com/aliyun/aliyun-sts-go-sdk/sts/ ...
- BZOJ4390: [Usaco2015 dec]Max Flow
BZOJ4390: [Usaco2015 dec]Max Flow Description Farmer John has installed a new system of N−1 pipes to ...
- WordPress升级出现Briefly unavailable for scheduled maintenance. Check back in a minute.
WordPress升级出现Briefly unavailable for scheduled maintenance. Check back in a minute. 打开博客时提示: Brief ...
- c语言高速推断一个数是偶数还是奇数
#include <stdio.h> int main() { int a; while(1) { printf("please input the number:\n" ...
- matlab使用usb和gige 网口相机
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...