题目链接:传送门

题意:

给定一棵树,求两个点之间的距离。

分析:

LCA 的模板题目 ans = dis[u]+dis[v] - 2*dis[lca(u,v)];

在线算法:详细解说 传送门

代码例如以下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 40010; struct nod{
int to,next,w;
}edge[maxn*2]; int head[maxn],ip,tot;
bool vis[maxn];
int R[maxn*2],ver[maxn*2];
int dp[maxn*2][25];
int first[maxn];
int dis[maxn]; void init(){
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
dis[1]=0,ip=0,tot=0;
} void add(int u,int v,int w){
edge[ip].to=v;
edge[ip].w=w;
edge[ip].next=head[u];
head[u]=ip++;
}
/***
ver[i]=x:第i个点是x.
first[i]=x: 点i第一次出现的位置是x
R[i]=x:第i个点的深度为x;
dis[i]=x;点i到根节点的距离为x.
***/
void dfs(int u,int dept){
vis[u]=true,ver[++tot]=u,first[u]=tot,R[tot]=dept;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
dis[v]=dis[u]+edge[i].w;
dfs(v,dept+1);
ver[++tot]=u,R[tot]=dept;
}
}
} void ST(int n){
for(int i=1;i<=n;i++) dp[i][0]=i;
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)<=n;j++){
int a = dp[j][i-1],b=dp[j+(1<<(i-1))][i-1];
if(R[a]<R[b]) dp[j][i]=a;
else dp[j][i]=b;
}
}
} int RMQ(int l,int r){
int k=0;
while(1<<(k+1)<=r-l+1)
k++;
int x = dp[l][k], y=dp[r-(1<<k)+1][k];
if(R[x]<R[y]) return x;
else return y;
} int LCA(int u,int v){
u=first[u],v=first[v];
if(u>v) swap(u,v);
return ver[RMQ(u,v)];
} int main(){
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<n-1;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(1,1);
ST(2*n-1);
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",dis[u]+dis[v]-2*dis[LCA(u,v)]);
}
}
return 0;
}

离线算法: 详细解说 传送门

代码例如以下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 40010; struct nod{
int u,v,next,w,lca;
}edge[maxn*2],edge1[maxn]; int par[maxn],ancestors[maxn];
int head[maxn],head1[maxn];
int dis[maxn],ip,ip1;
bool vis[maxn]; void init(){
memset(head1,-1,sizeof(head1));
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
for(int i=1;i<maxn;i++) par[i]=i;
dis[1]=0,ip1=0,ip=0;
} int find_par(int x){
if(x!=par[x]) return par[x]=find_par(par[x]);
return par[x];
} void Union(int u,int v){
u=find_par(u);
v=find_par(v);
if(u!=v) par[v]=u;
} void add(int u,int v,int w){
edge[ip].v=v;
edge[ip].w=w;
edge[ip].next=head[u];
head[u]=ip++;
} void add1(int u,int v){
edge1[ip1].u=u;
edge1[ip1].v=v;
edge1[ip1].lca=-1;
edge1[ip1].next=head1[u];
head1[u]=ip1++;
} void tarjan(int u){
vis[u]=1;
ancestors[u]=par[u]=u;
for(int i=head[u];i!=-1;i=edge[i].next){
int v = edge[i].v;
if(!vis[v]){
dis[v]=dis[u]+edge[i].w;
tarjan(v);
Union(u,v);
}
}
for(int i=head1[u];i!=-1;i=edge1[i].next){
int v = edge1[i].v;
if(vis[v]){
edge1[i].lca=edge1[i^1].lca=ancestors[find_par(v)];
}
}
} int main()
{
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<n-1;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
for(int i=0;i<m;i++){
int u,v;
scanf("%d%d",&u,&v);
add1(u,v);
add1(v,u);
}
tarjan(1);
for(int i=0;i<m;i++){
printf("%d\n",dis[edge1[i*2].u]+dis[edge1[i*2].v]-2*dis[edge1[i*2].lca]);
}
}
return 0;
}

HDU2586 How far away ?(LCA模板题)的更多相关文章

  1. hdu 2586 How far away?(LCA模板题+离线tarjan算法)

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. HDU 2586——How far away ?——————【LCA模板题】

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. HDU 2586 (LCA模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 ...

  4. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  5. POJ 1986 - Distance Queries - [LCA模板题][Tarjan-LCA算法]

    题目链接:http://poj.org/problem?id=1986 Description Farmer John's cows refused to run in his marathon si ...

  6. [hdu 2586]lca模板题(在线+离线两种版本)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 在线版本: 在线方法的思路很简单,就是倍增.一遍dfs得到每个节点的父亲,以及每个点的深度.然后 ...

  7. HDU 2586 How far away ? 离线lca模板题

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  8. ZOJ 3195 Design the city (LCA 模板题)

    Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terribl ...

  9. HDU 2586 How far away ?【LCA模板题】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给你N个点,M次询问.1~N-1行输入点与点之间的权值,之后M行输入两个点(a,b)之间的最 ...

随机推荐

  1. 编译android-4.3.1_r源代码并刷到自己的Galaxy Nexus I9250真机上

    编译android-4.3.1_r源代码并刷到自己的Galaxy Nexus I9250真机上 作者:雨水  日期:2014-04-30 编译源码的目的还是为了自己改动源码,然后还可以执行在相应的手机 ...

  2. 【Demo 0004】Java基础-类封装性

    本章学习要点:       1.  Java封装特性;       2.  掌握类的定义:       3.  掌握类的调用方法; 一.封装特性        Java 纯面向对象语言,面向对象语言遵 ...

  3. myBatis 基础测试 表关联关系配置 集合 测试

    myBatis 基础测试 表关联关系配置 集合 测试 测试myelipse项目源码 sql 下载 http://download.csdn.net/detail/liangrui1988/599388 ...

  4. C文件操作的语言fgets()

        谈fgets(..)功能.     原型  char *  fgets(char * s, int n,FILE *stream);     參数:          s: 字符型指针.指向存 ...

  5. 使用visual c++ 2005远程调试64位系统上32位与64位程序

    一直都挺喜欢使用visual c++远程调试代码,它能展现给我们当时代码执行最真实的情景,今天有时间记录一下,以免以后忘了. 远程调试需要在被调试端安装服务器,对于visual c++ 2005来说调 ...

  6. cronjob不跑得原因

    能是环境的不同,能够在cronjob中加个env > /tmp/env.output查看 应用要同一时候输出标准错误合标准输出到一个文件能够&> /tmp/t

  7. hdu 5115 Dire Wolf

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5115 题目分类:区间dp 题意:有n只狼,每只狼有两种属性,一种攻击力一种附加值,我们没杀一只狼,那么 ...

  8. 小心LinkedHashMap的get()方法(转)

    这是一个来自实际项目的例子,在这个案例中,有同事基于jdk中的LinkedHashMap设计了一个LRUCache,为了提高性能,使用了 ReentrantReadWriteLock 读写锁:写锁对应 ...

  9. 新闻专栏~ART让Android更流畅

    潘鹏在CSDN上原创,如其它站点转载请注意排版和写明出处: ART.Android新的内存垃圾回收机制 ART的优点:代码加载速度加快----编译次数降低 Android的卡顿是由于内存垃圾回收机制. ...

  10. C#使用Redis集群缓存

    C#使用Redis集群缓存 本文介绍系统缓存组件,采用NOSQL之Redis作为系统缓存层. 一.背景 系统考虑到高并发的使用场景.对于并发提交场景,通过上一章节介绍的RabbitMQ组件解决.对于系 ...