LCA 离线的Tarjan算法 poj1330 hdu2586
LCA问题有好几种做法,用到(tarjan)图拉算法的就有3种。具体可以看邝斌的博客。http://www.cnblogs.com/kuangbin/category/415390.html
几天的学习,我就弄懂了离线的Tarjan算法。在此,先鄙视一下哈工大出版的《图论及应用》,离线的Tarjan算法的模版用不了。害我白忙活。
poj1330的代码可以直接用来当模版。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int f[N], r[N], anc[N];
bool vis[N];
struct node
{
int to,next;
}edge[N*];
int head[N],tot;
void addedge(int i, int j)
{
edge[tot].to=j;edge[tot].next=head[i];head[i]=tot++;
edge[tot].to=i;edge[tot].next=head[j];head[j]=tot++;
}
struct NODE
{
int to,next,index;//index(查询编号)
}query[N*];
int h[N], res[N*], tt, q;
bool flag[N];
void add_q(int i, int j, int k)
{
query[tt].to=j;query[tt].next=h[i];query[tt].index=k;h[i]=tt++;
query[tt].to=i;query[tt].next=h[j];query[tt].index=k;h[j]=tt++;
}
void init(int n)
{
for(int i=;i<=n;i++)
{
f[i]=-;
r[i]=;
vis[i]=;
anc[i]=;
flag[i]=;
tot=tt=;
}
memset(head,-,sizeof(head));
memset(h,-,sizeof(h));
}
int Find(int x)
{
if(-==f[x]) return x;
return f[x]=Find(f[x]);
}
void Link(int x,int y)
{
int a=Find(x),b=Find(y);
if(a!=b)
{
if(r[a]<=r[b]) {f[a]=b; r[b]+=r[a];}
else {f[b]=a; r[a]+=r[b];}
}
}
void LCA(int u)
{
anc[u]=u;
vis[u]=;
for(int k=head[u];k!=-;k=edge[k].next)
{
int v=edge[k].to;
if(vis[v]) continue;
LCA(v);
Link(u,v);
anc[Find(u)]=u;
}
for(int k=h[u];k!=-;k=query[k].next)
{
int v=query[k].to;
if(vis[v])
{
res[query[k].index]=anc[Find(v)];
}
}
}
int main()
{
//freopen("test.txt","r",stdin);
int T,n,u,v,i;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init(n);
for(i=;i<n;i++)
{
scanf("%d%d",&u,&v);
flag[v]=;
addedge(u,v);
}
q=;
for(i=;i<q;i++)
{
scanf("%d%d",&u,&v);
add_q(u,v,i);
}
int root;
for(i=;i<=n;i++)
if(!flag[i]) {root=i; break;}
LCA(root);
for(i=;i<q;i++)
printf("%d\n",res[i]);
}
return ;
}
hdu2586的要求有些提高,还要求距离。假如要求u和v两点的距离,可以通过求u和v到根结点的距离,还有他们的LCA到根节点的距离。公式是dis[u] + dis[v] -2*dis[LCA[u,v]]。
//hdu2586 O(n+q) #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int f[N], r[N], anc[N];
bool vis[N];
struct node
{
int to,next,w;
}edge[N*];
int head[N],tot;
void addedge(int i, int j,int w)
{
edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
edge[tot].to=i;edge[tot].w=w;edge[tot].next=head[j];head[j]=tot++;
}
struct NODE
{
int to,next,index;//index(查询编号)
}query[N*];
int h[N], res[N*], tt, q, dist[N];
bool flag[N];
void add_q(int i, int j, int k)
{
query[tt].to=j;query[tt].next=h[i];query[tt].index=k;h[i]=tt++;
query[tt].to=i;query[tt].next=h[j];query[tt].index=k;h[j]=tt++;
}
void init(int n)
{
for(int i=;i<=n;i++)
{
f[i]=-;
r[i]=;
vis[i]=;
anc[i]=;
flag[i]=;
tot=tt=;
}
memset(head,-,sizeof(head));
memset(h,-,sizeof(h));
}
int Find(int x)
{
if(-==f[x]) return x;
return f[x]=Find(f[x]);
}
void Link(int x,int y)
{
int a=Find(x),b=Find(y);
if(a!=b)
{
if(r[a]<=r[b]) {f[a]=b; r[b]+=r[a];}
else {f[b]=a; r[a]+=r[b];}
}
}
void LCA(int u)
{
anc[u]=u;
vis[u]=;
for(int k=head[u];k!=-;k=edge[k].next)
{
int v=edge[k].to;
if(vis[v]) continue;
dist[v]=dist[u]+edge[k].w;
LCA(v);
Link(u,v);
anc[Find(u)]=u; }
for(int k=h[u];k!=-;k=query[k].next)
{
int v=query[k].to;
if(vis[v])
res[query[k].index]=anc[Find(v)];
}
}
int a[N],b[N];
int main()
{
//freopen("test.txt","r",stdin);
int T,n,u,v,i,m,w;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
init(n);
for(i=;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
flag[v]=;
addedge(u,v,w);
}
for(i=;i<q;i++)
{
scanf("%d%d",&u,&v);
a[i]=u;b[i]=v;
add_q(u,v,i);
}
int root;
for(i=;i<=n;i++)
if(!flag[i]) {root=i; break;}
dist[root]=;
LCA(root);
for(i=;i<q;i++)
printf("%d\n",dist[a[i]]+dist[b[i]]-*dist[res[i]]);
}
return ;
}
LCA 离线的Tarjan算法 poj1330 hdu2586的更多相关文章
- (转载)LCA问题的Tarjan算法
转载自:Click Here LCA问题(Lowest Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两 ...
- LCA 离线做法tarjan
tarjan(int u) { int v; for(int i=h[u];i;i=nex[i])//搜索边的 { v=to[i]; tarjan(v); marge(u,v); vis[v]=; } ...
- Tarjan算法离线 求 LCA(最近公共祖先)
本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig ...
- LCA离线算法Tarjan的模板
hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #inc ...
- 【POJ 1330 Nearest Common Ancestors】LCA问题 Tarjan算法
题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从 ...
- POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从 ...
- 『追捕盗贼 Tarjan算法』
追捕盗贼(COCI2007) Description 为了帮助警察抓住在逃的罪犯,你发明了一个新的计算机系统.警察控制的区域有N个城市,城市之间有E条双向边连接,城市编号为1到N. 警察经常想在罪犯从 ...
- [POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)
题目链接:http://poj.org/problem?id=1330 题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下. 个人感觉tarjan算法是利用了dfs序和节点深度的关系 ...
- POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)
Closest Common Ancestors Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 13372 Accept ...
随机推荐
- SGU495Kids and Prizes 数学期望
题意: 有n个奖品,m个人排队来选礼物,对于每个人,他打开的盒子,可能有礼物,也有可能已经被之前的人取走了,然后把盒子放回原处.为最后m个人取走礼物的期望. 题解: 本道题与之前的一些期望 DP 题目 ...
- WERTYU(WERTYU, UVa10082)
把手放在键盘上时,稍不注意就会往右错一 位.这样,输入Q会变成输入W,输入J会变成输 入K等.键盘如图所示. 输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子.输入保 证合法, ...
- 51nod1289 大鱼吃小鱼
有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右).问足够长的时间之后 ...
- 磁盘及文件系统管理(以及btrfs)
Linux系统管理 磁盘分区及文件系统管理 raid lvm 网络属性管理 程序包管理 sed及awk 进程查看和管理 内核管理(内核的编译和安装) 系统启动流程 定制,编译内核,busybox 系统 ...
- JavaScript基础的记录
一.JavaScript的六种基本类型: 基本数据类型: String.Number.Boolean.Null.Undefined 引用数据类型: Object 二.强制类型转换: 主要指将其他的数据 ...
- 【Codeforces 639B】Bear and Forgotten Tree 3
[链接] 我是链接,点我呀:) [题意] [题解] 首先,因为高度是h 所以肯定1下面有连续的h个点依次连成一条链.->用了h+1个点了 然后,考虑d这个约束. 会发现,形成d的这个路径,它一定 ...
- Spring Cloud-Ribbon实现客户端的服务均衡(三)
客户端负载均衡与服务端负载均衡 服务端负载均衡 通过服务端负载均衡设备维护的服务清单根据算法(轮训 权重负载 流量负载)取出服务地址 进行转发 客户端负载 将指定服务的服务清单订单(注册中心)下来 在 ...
- javascript-jsonp的用法
原文地址 $.ajax({ type: "get", async: false, url: "ajax.ashx", dataType: "jsonp ...
- GIS+=地理信息+容器技术(1)——容器技术概述
-------------------------------------------------------------------------------------- Blog: http ...
- Notepad++如何编译、运行Java
首先要让Notepad++编译和运行Java,前提是电脑里已经配置好了Java的环境(这里可以参考我博客里关于Java环境配置的那篇随笔). 在Notepad++上面的选项栏中找到 插件---> ...