题目大意:

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

这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去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. POJ 3260 多重背包+完全背包

    前几天刚回到家却发现家里没网线 && 路由器都被带走了,无奈之下只好铤而走险尝试蹭隔壁家的WiFi,不试不知道,一试吓一跳,用个手机软件简简单单就连上了,然后在浏览器输入192.168 ...

  2. Oracle查看表结构的几种方法

    1,DESCRIBE 命令 使用方法如下: SQL> describe nchar_tst(nchar_tst为表名) 显示的结果如下:  名称                         ...

  3. tinyXml直接解析XML字符串

    一直都用tinyxml直接LoadFile来解析XML,发现原来也可以直接解析XML字符串. XML文件: <?xml version=\"1.0\" encoding=\& ...

  4. C#_观察者模式

    假设有一个软件公司,每当有新产品推出,就把信息通知到一些客户. 把通知这个动作抽象成一个接口. public interface IService { void Notif(); } 客户如果想获得通 ...

  5. 转!!java泛型概念(泛型类,接口,方法)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ...

  6. JSON 语法规则详解

    JSON 的语法规则十分简单,无论用何种方法总结都只有数条而已,它参考了 C 语言家族的一些习惯,学习起来并不会感到陌生. 回顾JSON 的五点语法 1)- 数组(Array)用方括号("[ ...

  7. 快速了解AngularJs HTTP响应拦截器

    任何时候,如果我们想要为请求添加全局功能,例如身份认证.错误处理等,在请求发送给服务器之前或服务器返回时对其进行拦截,是比较好的实现手段. angularJs通过拦截器提供了一个从全局层面进行处理的途 ...

  8. drupal 2016-11-3

    我随意定义了一个hook menu发现里面的内容很快就加入到了navigation menu里面.

  9. java 多线程3(线程安全)

    需求:模拟三个窗口同时买票. 问题1:static 修饰num,只创建一份在内存中,要不就会创建3份. 问题2:线程安全问题.(代码重1的红色字体) 出现的原因:存在两个或两个以上的线程对象,而且线程 ...

  10. java 导入包(误区)

    java的导入包语句的作用仅仅是简化书写,很多时候我们都误以为是将一个类导入到内存中. 如果是这样,那么运行的效率会很慢.