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 ...
随机推荐
- 关于jQuery.form中formSerialize()等函数的适用对象
几个月前写一个页面,要用到Ajax提交,于是写了几行jQuery: …… var formData = $("form")[0].formSerialize(); …… 然后死活调 ...
- scrapy获取重定向之前的url
通过 response.request.meta['redirect_urls'] 来获取跳转之前的链接
- NFS实时备份
方法一(inotify+rsync): 1.安装inotify-tools(客户端)[监听工具],实现数据属实备份检查目录是否有如下文档,没有表示操作系统不支持 ls -l /proc/sys/fs/ ...
- sql语句学习(NOT EXISTS 和 NOT IN )
NOT EXISTS SELECT a.*FROM t_user aWHERE a.id_card LIKE '%3203821995100%'AND NOT EXISTS ( SELECT id F ...
- 使用VS Code断点调试PHP
vs code 使用一款杰出的轻量级代码编辑器,其中的插件工具不胜枚举而且还在不断增加.使用 vs code 调试 php 代码更是方便简洁,下面我们来一起看一下. 1. 安装 XDebug 扩展 调 ...
- Django(七)
一.ModelForm操作及验证 1.class Meta:class Meta: #注意以下字段不能加逗号 model = models.UserInfo #这里的all代指所用的字段,也可以是一个 ...
- POJ 3528
三维凸包 /* 增量法求凸包.选取一个四面体,同时把它各面的方向向量向外,增加一个点时,若该点与凸包上的某些面的方 向向量在同一侧,则去掉那些面,并使某些边与新增点一起连成新的凸包上的面. */ #i ...
- _DataStructure_C_Impl:求图G中从顶点u到顶点v的一条简单路径
#pragma once #include<stdio.h> #include<stdlib.h> #define StackSize 100 typedef int Data ...
- 跟我学Java多线程——线程池与堵塞队列
前言 上一篇文章中我们将ThreadPoolExecutor进行了深入的学习和介绍,实际上我们在项目中应用的时候非常少有直接应用ThreadPoolExecutor来创建线程池的.在jdk的api中有 ...
- Jetty:部署到Jetty
Web应用的框架 标准Jetty公布版本号能部署标准servlet Spec Web应用和Jetty内部ContextHandler部署描写叙述符,或者两者的一个混合. Web应用是可部署的动态(se ...