题目大意:

多点形成一棵树,树上边有权值,给出一堆询问,求出每个询问中两个点的距离

这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去2倍的最近公共祖先到根节点的距离

这是自己第一道lca题目

学习了两种方法

第一种在ST算法,利用RMQ思想预处理

 /*在线ST算法*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 40010 int first[N] , k; struct Edge{
int x , y , w , next;
Edge(){}
Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
}e[N<<]; void add_edge(int x , int y , int w)
{
e[k] = Edge(x , y , w , first[x]);
first[x] = k++;
}
int dp[N<<][];
int id[N<<] , dep[N<<] , dis[N] , No[N] , dfs_clock;
void dfs(int u , int f , int d)
{
id[++dfs_clock] = u , No[u] = dfs_clock , dep[dfs_clock] = d;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f) continue;
dis[v] = dis[u]+e[i].w;
dfs(v , u , d+);
id[++dfs_clock] = u , dep[dfs_clock] = d;
}
} void ST(int n)
{
for(int i= ; i<=n ; i++) dp[i][] = i;
for(int j= ; (<<j)<=n ; j++){
for(int i= ; i+(<<j)-<=n ; i++){
int a = dp[i][j-] , b = dp[i+(<<(j-))][j-];
dp[i][j] = dep[a]<dep[b]?a:b;
}
}
} int RMQ(int l , int r)
{
int k=;
while((<<(k+))<=r-l+) k++;
int a = dp[l][k] , b = dp[r-(<<k)+][k];
return dep[a]<dep[b]?a:b;
} int LCA(int u , int v)
{
int x = No[u] , y = No[v];
if(x>y) swap(x , y);
return id[RMQ(x , y)];
} int n , m; int main()
{
// freopen("in.txt" , "r" , stdin);
int T , x , y , w;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d" , &n , &m);
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d%d" , &x , &y , &w);
add_edge(x , y , w);
add_edge(y , x , w);
}
dfs_clock = ;
dis[] = ;
dfs( , , );
ST(*n-);
while(m--){
scanf("%d%d" , &x , &y);
int anc = LCA(x , y);
printf("%d\n" , dis[x]-*dis[anc]+dis[y]);
}
}
return ;
}

ST算法

第二种是离线的Tarjan算法,利用并查集的思想解决

 /*在线ST算法*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 40010
#define M 205
int first[N] , k; struct Edge{
int x , y , w , next;
Edge(){}
Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
}e[N<<]; int _first[N] , _k; struct Que{
int v , lca , next;
Que(){}
Que(int v , int lca , int next):v(v),lca(lca),next(next){}
}eq[M<<]; void add_edge(int x , int y , int w)
{
e[k] = Edge(x , y , w , first[x]);
first[x] = k++;
} void add_que_edge(int x , int y)
{
eq[_k] = Que(y , , _first[x]);
_first[x] = _k++;
} int fa[N] , dis[N];
bool vis[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void tarjan(int u)
{
vis[u] = true , fa[u] = u;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(vis[v]) continue;
dis[v] = dis[u]+e[i].w;
tarjan(v);
fa[v] = u;
}
for(int i=_first[u] ; ~i ; i=eq[i].next){
int v = eq[i].v;
if(vis[v]) eq[i].lca = eq[i^].lca = find(eq[i].v);
}
}
int n , m; int main()
{
// freopen("in.txt" , "r" , stdin);
int T , x , y , w;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d" , &n , &m);
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d%d" , &x , &y , &w);
add_edge(x , y , w);
add_edge(y , x , w);
}
memset(_first , - , sizeof(_first));
_k = ;
for(int i= ; i<m ; i++){
scanf("%d%d" , &x , &y);
add_que_edge(x , y);
add_que_edge(y , x);
}
memset(vis , , sizeof(vis));
tarjan();
for(int i= ; i<m* ; i+=){
int lca = eq[i].lca;
printf("%d\n" , dis[eq[i].v]-*dis[lca]+dis[eq[i^].v]);
}
}
return ;
}

Tarjan算法

HDU 2586 LCA的更多相关文章

  1. HDU 2586 (LCA模板题)

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

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

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

  3. HDU 2586 ( LCA/tarjan算法模板)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离 思路:求出两个村庄的LCA,d ...

  4. hdu 2586(LCA在线ST)

    How far away ? Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): A ...

  5. hdu - 2586 (LCA板子题)

    传送门 (这次的英文题面要比上一个容易看多了) (英语蒟蒻的卑微) 又是一个很裸的LCA题 (显然,这次不太容易打暴力咧) (但听说还是有大佬用dfs直接a掉了) 正好 趁这个机会复习一下LCA 这里 ...

  6. hdu 2586 lca在线算法(朴素算法)

    #include<stdio.h> #include<string.h>//用c/c++会爆栈,用g++ac #define inf 0x3fffffff #define N ...

  7. HDU 2586 How far away ? (LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 LCA模版题. RMQ+LCA: #include <iostream> #incl ...

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

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

  9. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

随机推荐

  1. 【转载】【Centos linux系统】命令行(静默)安装oracle 11gR2

    [原文]:http://blog.chinaunix.net/uid-23886490-id-3565998.html 一.安装前准备 1.内存及swap要求 至于swap如何添加,后文将提到 gre ...

  2. bzoj2154(莫比乌斯反演)

    又是一道经典题. 1.学习了下O(n) 的做法. // // main.cpp // bzoj2154 // // Created by New_Life on 16/7/7. // Copyrigh ...

  3. Java Date与SimpleDateFormat

    最近在弄一些涉及到时间处理的项目.本来自己写了一个时间转换函数,虽然能用但是过于麻烦而且不够规范,于是学习了下java自带的时间处理的类. public class Timechg { public ...

  4. MEAN-全栈javascript开发框架

    引言 使用JavaScript能够完整迅速做出Web应用程序,目前一套工具包括MongoDB.ExpressJS,AngularJS和Node.js越来越受到欢迎,其开发的灵活性和易用性加快开发效率, ...

  5. android用shape给linearLayout设置边框,怎样只保留底部或顶部的边框,把其它三个方向的边框去掉呢?

    http://bbs.csdn.net/topics/390485215 这种方法只是两个颜色块相减而已 <?xml version="1.0" encoding=" ...

  6. WEB网页插件 如何实现 选择上传图片路径 【高级问题】

    发表于 2010-10-22 12:11 | |只看楼主       按键精灵程序里面的WEB网页插件 如何实现 选择上传图片路径 我想在上传图片的选框设置图片路径为 C:\fakepath\001. ...

  7. xcode6 AsynchronousTesting 异步任务测试

    xcode集成了非常方便的测试框架,XCTest 在xcode6之后,提供了 <XCTest/XCTestCase+AsynchronousTesting.h> 利用此我们可以直接在XCT ...

  8. dede会员指定栏目发布文章

    后台——核心——网站栏目管理——修改栏目——常规选项——支持投稿

  9. Unity的HTC VIVE SDK研究(手柄按键功能的研究,比较详细)

    http://blog.csdn.net/ystistheking/article/details/51553237 想交流的朋友我们可以微博互粉,我的微博黑石铸造厂厂长 ,缺粉丝啊 .....求粉求 ...

  10. 屏幕输出VS文件输出

     问题1:我们在编写程序时经常需要数一些数据到屏幕,来查看我们的结果是否正确,虽然直接输出到屏幕,查看起来呢很方便,但当数据量很大时,需要耗费大量的时间.于是我们想到能不能通过输出到文件来减少时间 ...