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 ...
随机推荐
- python 生成HTmL报告页面
计划做一个html页面 py3.4 代码: # -*- coding=utf-8 -*- # import time,os class Template_mixin(object): "&q ...
- 深度学习应用在推荐系统的论文-----A Novel Deep Learning-Based Collaborative Filtering Model for Recommendation System
1.题目:一种新的基于深度学习的协同过滤推荐系统 2.摘要: 以协同过滤(CF)为基础的模型主要获取用户和项目的交互或者相关性.然而,现有的基于CF的方法只能掌握单一类型的关系,如RBM,它只能获取用 ...
- 一个简单的执行程序的GNU automake自动生成Makefile的方法及案例
一个简单的执行程序的GNU automake自动生成Makefile的方法及案例 在GNU的世界里,存在Automake这样的工具进行自动生成Makefile文件,automake是由Perl语言编写 ...
- Top English interview Q&A part 2.
https://www.zhihu.com/question/19666878 1.how do you handle failure? I have always lived by the maxi ...
- Zend Studio快捷键汇总
应用场景 快捷键 功能 查看快捷键 ctrl+shift+l 显示所有快捷键列表 查看和修改快捷键 打开Window->Preferences->General->keys 修改 ...
- Linux命令及全称(部分)
man: manual 意思是手册,可以用这个命令查询其他命令的用法. pwd:print working directory 显示当前工作路径. su:swith user 切换用户,切换 ...
- winrar为啥有广告了?能去掉么?
winrar为啥有广告了?能去掉么? 学习了:http://blog.csdn.net/chenchunlin526/article/details/54580686 学习了:https://jing ...
- 一见钟情Sublime
打开 preferences -> Setting-User,加入下面代码 { "font_size": 14, "ignored_packages": ...
- jQuery必知要点(一)
1. jQuery框架的显著特点. jQuery强调的理念是写的少,做的多(write less.do more). 其主要特点有:轻量级.强大的选择器.美丽的DOM操作封装.可靠的事件处理机制.完好 ...
- 125条常见的java面试、笔试题大汇总
1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解所有问题,而仅仅是选择当中的一部分,临时不用部分细节.抽象包含两个方面,一是过程抽象. ...