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的更多相关文章

  1. (转载)LCA问题的Tarjan算法

    转载自:Click Here LCA问题(Lowest Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两 ...

  2. 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]=; } ...

  3. Tarjan算法离线 求 LCA(最近公共祖先)

    本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig ...

  4. LCA离线算法Tarjan的模板

    hdu 2586:题意:输入n个点的n-1条边的树,m组询问任意点 a b之间的最短距离 思路:LCA中的Tarjan算法,RMQ还不会.. #include <stdio.h> #inc ...

  5. 【POJ 1330 Nearest Common Ancestors】LCA问题 Tarjan算法

    题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从 ...

  6. POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)

    题目链接:http://poj.org/problem?id=1330 题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先. 数据范围:n [2, 10000] 思路:从 ...

  7. 『追捕盗贼 Tarjan算法』

    追捕盗贼(COCI2007) Description 为了帮助警察抓住在逃的罪犯,你发明了一个新的计算机系统.警察控制的区域有N个城市,城市之间有E条双向边连接,城市编号为1到N. 警察经常想在罪犯从 ...

  8. [POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)

    题目链接:http://poj.org/problem?id=1330 题意就是求一组最近公共祖先,昨晚学了离线tarjan,今天来实现一下. 个人感觉tarjan算法是利用了dfs序和节点深度的关系 ...

  9. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

随机推荐

  1. 单链表每k个节点为一组进行反转(最后不满k个时不反转)

    public class LinkReverse2 { public static Node mhead=null; public static Node mtail=null; public sta ...

  2. 【转载】VMware完全卸载

    出现安装时出现vmwareworkstationxxx.msi failed问题是官方解决方案...真心详细. http://kb.vmware.com/selfservice/microsites/ ...

  3. svn_精简版【极速安装】

    1.进入官网下载:http://tortoisesvn.net/ 2.进行安装. 3.官方下载汉化包 [32 位,64位] 4.安装完汉化包后,右键->Settings 5.选择语言包,确定就o ...

  4. 利用Socket 客户端---->服务端 传送文件到指定路径,并返回一个友好的回馈

    首先盲写的一个传输文件的方法,但测试发现了一个非常不容易发现的问题,这里先说明一下. 错误的代码如下: package com.TCP.java; import java.io.File; impor ...

  5. java陷阱之Array.asList

    List<Integer> numbers= Arrays.asList(new Integer[] {1,2,3}); numbers.add(3); 运行这段代码会抛出 java.la ...

  6. Navicat Premium (patch and keygen)

    标签:Navicat 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://sofar.blog.51cto.com/353572/13 ...

  7. 洛谷 P1198 BZOJ 1012 [JSOI2008]最大数

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...

  8. SIGPROF和SIGALRM使用总结

    这几天,被公司的两个模块的程序好好的搞了一下,开始以为是SHELL的问题,仔细研究了以下,原来没有想象的那么复杂!!!       关键在使用的信号SIGALRM 上,两个进程都用可SIGALRM 信 ...

  9. C++ exit 与 return 浅析

    [摘要] 本文从代码形式.经常使用方式,相关概念,调用关系和比較分析,这5个维度浅析 exit 与 return 在C++的同样点与差别. [常见形式] exit(0):   正常执行程序并退出程序. ...

  10. POJ1789&amp;ZOJ2158--Truck History【最小生成树变形】

    链接:http://poj.org/problem?id=1789 题意:卡车公司有悠久的历史,它的每一种卡车都有一个唯一的字符串来表示,长度为7,它的全部卡车(除了第一辆)都是由曾经的卡车派生出来的 ...