题目大意:

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

这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去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. Android开发中退出程序几种方法

    参考:http://johncookie.iteye.com/blog/890734 Android程序有很多Activity,比如说主窗口A,调用了子窗口B,子窗口B又调用子窗口C,back返回子窗 ...

  2. Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解

    MainActivity如下: package cc.c; import android.app.Activity; import android.os.Bundle; import android. ...

  3. OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

    OpenGL中图形绘制后,往往需要一系列的变换来达到用户的目的,而这种变换实现的原理是又通过矩阵进行操作的.opengl中的变换一般包括视图变换.模型变换.投影变换等,在每次变换后,opengl将会呈 ...

  4. RTB

    RTB —— Real Time Bidding 的简称,就是实时竞价.跟传统购买形式相比,RTB是在每一个广告展示曝光的基础上进行竞价,就是每一个PV都会进行一次展现竞价,谁出价高,谁的广告就会被这 ...

  5. hiho_1048_状态压缩2

    题目大意 用1x2的单元拼接出 NxM的矩形,单元可以横放或者纵放,N < 1000, M <= 5. 求不同的拼接方案总数. 分析 计算机解决问题的基本思路:搜索状态空间.如果采用dfs ...

  6. Redis常用的基本命令整理

    SET key value [EX seconds] [PX milliseconds] [NX|XX] 设置缓存 K-V,如果 key 已经存在,则重写 EX seconds -- 设置过期时间, ...

  7. form in drupal

    qin_form_ajax_example_form($form, &$form_state)类似函数的参数永远都是一样的,最多把$form前面也加上& 当没有实现页面跳转时,$for ...

  8. table合并单元格colspan和rowspan .

    colspan和rowspan这两个属性用于创建特殊的表格. colspan是“column span(跨列)”的缩写.colspan属性用在td标签中,用来指定单元格横向跨越的列数: 在浏览器中将显 ...

  9. JSONObject和JSONArray使用

    1.所依赖JAR包 要使程序可以运行必须引入JSON-lib包,JSON-lib包同时依赖于以下的JAR包: commons-lang.jar commons-beanutils.jar common ...

  10. Azure 云平台用 SQOOP 将 SQL server 2012 数据表导入 HIVE / HBASE

    My name is Farooq and I am with HDinsight support team here at Microsoft. In this blog I will try to ...