题目大意:

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

这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去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. 4 BOM编程

    4 BOM编程 编程基础 全称 Browser Object Model,浏览器对象模型. JavaScript是由浏览器中内置的javascript脚本解释器程序来执行javascript脚本语言的 ...

  2. [js] 跨域

    原文链接:http://www.cnblogs.com/scottckt/archive/2011/11/12/2246531.html 什么是跨域? 首先什么是跨域,简单地理解就是因为JavaScr ...

  3. 使用kaptcha生成验证码

    原文:http://www.cnblogs.com/xdp-gacl/p/4221848.html kaptcha是一个简单好用的验证码生成工具,通过配置,可以自己定义验证码大小.颜色.显示的字符等等 ...

  4. nosql简述

    1.NoSQL数据库概念 NoSQL数据库是非关系型数据库,主要是针对关系型数据库而言,它主要是用来解决半结构化数据和非机构化数据的存储问题. 2.为什么使用NoSQL数据库? (1)对数据库的高并发 ...

  5. php中高级基础知识点

    1. 基本知识点 HTTP协议中几个状态码的含义:1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 代码   说明 100   (继续) 请求者应当继续提出请求. 服务器返回此代码 ...

  6. Hive优化

    hive.optimize.cp=true:列裁剪hive.optimize.prunner:分区裁剪hive.limit.optimize.enable=true:优化LIMIT n语句hive.l ...

  7. 项目解析- JspLibrary - part2

    banner.jsp 验证用户是否登录 <%String manager=(String)session.getAttribute("manager"); //验证用户是否登 ...

  8. vc++编译libtiff4.0.4

    目录 第1章简介    1 第2章命令行编译    2 2.1 编译    2 2.1.1 使用VC++2010编译    2 2.1.2 使用VC++6编译    4 2.2 生成的文件    5 ...

  9. oneproxy---为实战而生之安装篇

       OneProxy是一款数据库中间件,与目前市面上的TDDL.MySQL-Proxy属于同类型产品.我们坚持研发OneProxy是基于如下几点考虑:       1. 我们不想被某一种开发语言绑定 ...

  10. 布局两列div等高方法

    一.左右布局,左侧div绝对定位,外div相对定位 <!DOCTYPE html> <html lang="en"> <head> <me ...