Problem Description
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
       
Input
First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
 
Output
For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
 
Sample Input
2
3 2
1 2 10
3 1 15
1 2
2 3
 
2 2
1 2 100
1 2
2 1
 
Sample Output
10
25
100
100

LCA_倍增是LCA的在线算法,时间和空间复杂度分别是O((n+q)log n)和O(n log n)。
对于这个算法,我们从最暴力的算法开始:
①如果a和b深度不同,先把深度调浅,使他变得和浅的那个一样
②现在已经保证了a和b的深度一样,所以我们只要把两个一起一步一步往上移动,直到他们到达同一个节点,也就是他们的最近公共祖先了。

/*
author:gsw
data:2018.04.30
link:http://acm.hdu.edu.cn/showproblem.php?pid=2586
account:tonysave
*/
#define ll long long
#define IO ios::sync_with_stdio(false);
#define maxn 40005 #include<vector>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int t,n,m;
class Node{
public:
int nex,len;
};
vector<Node> tree[maxn];
int dis[maxn];int deep[maxn];
int fa[maxn]; void init()
{
for(int i=;i<n;i++)
tree[i].clear();
memset(dis,,sizeof(dis));
memset(deep,,sizeof(deep));
memset(fa,,sizeof(fa));
}
Node ne;
void dfs(int num,int faa)
{
for(int i=;i<tree[num].size();i++)
{
ne=tree[num][i];
if(ne.nex!=faa)
{
fa[ne.nex]=num;
deep[ne.nex]=deep[num]+;
dis[ne.nex]=dis[num]+ne.len;
dfs(ne.nex,num);
}
}
}
int lca(int a,int b)
{
if(deep[a]>deep[b])
swap(a,b);
while(deep[b]>deep[a])
b=fa[b];
while(a!=b)
a=fa[a],b=fa[b];
return a;
} int main()
{
int a,b,c;Node tem;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=;i<n-;i++)
{
scanf("%d%d%d",&a,&b,&c);
tem.nex=b;tem.len=c;
tree[a].push_back(tem);
tem.nex=a;
tree[b].push_back(tem);
}
dfs(,);
for(int i=;i<m;i++)
{
scanf("%d%d",&a,&b);
int ans=lca(a,b);
ans=dis[a]+dis[b]-*dis[ans];
printf("%d\n",ans);
}
}
}

HDU2586---How far away ?(lca算法)的更多相关文章

  1. LCA算法

    LCA算法: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共 ...

  2. 【图论】tarjan的离线LCA算法

    百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效 ...

  3. LCA算法解析-Tarjan&倍增&RMQ

    原文链接http://www.cnblogs.com/zhouzhendong/p/7256007.html UPD(2018-5-13) : 细节修改以及使用了Latex代码,公式更加美观.改的过程 ...

  4. LCA算法倍增算法(洛谷3379模板题)

    倍增(爬树)算法,刚刚学习的算法.对每一个点的父节点,就记录他的2k的父亲. 题目为http://www.luogu.org/problem/show?pid=3379 第一步先记录每一个节点的深度用 ...

  5. LCA 算法(二)倍增

     介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上.   代码:   //LCA:Doubly #include<cstdio> #define swap(a, ...

  6. LCA 算法(一)ST表

    介绍一种解决最近公共祖先的在线算法,st表,它是建立在线性中的rmq问题之上.   代码:   //LCA: DFS+ST(RMQ) #include<cstdio> #include&l ...

  7. LCA算法总结

    LCA问题(Least Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找 ...

  8. [算法整理]树上求LCA算法合集

    1#树上倍增 以前写的博客:http://www.cnblogs.com/yyf0309/p/5972701.html 预处理时间复杂度O(nlog2n),查询O(log2n),也不算难写. 2#st ...

  9. LCA算法笔记

    LCA,最近公共祖先,实现有多种不同的方法,在树上的问题中有着广泛的应用,比如说树上的最短路之类. LCA的实现方法有很多,比如RMQ.树链剖分等. 今天来讲其中实现较为简单的三种算法: RMQ+时间 ...

  10. 对各种lca算法的理解

    1.RMQ+ST 首先注意这个算法的要素:结点编号,dfs序,结点深度. 首先dfs,求出dfs序,同时求出每个结点的深度.然后st算法,维护深度最小的结点编号(dfs序也可以,因为他们俩可以互相转换 ...

随机推荐

  1. sequel 远程连接 MySQL 连接错误Can't connect to MySQL server on (61)

    Mac sequel Pro链接时报错Can’t connect to MySQL server on ‘xx.xx.xx.xx’ (61). PS. win版Navicat 报错Can’t conn ...

  2. 关于Extjs6.0 controller文件过大,实现模块化分离

    Extjs一般都是一个视图对应着一个controller 一旦碰到视图中逻辑过于繁琐造成controller文件过大不利于维护和修改,所以要通过混入mixins混入功能来实现模块化! 首先创建一个视图 ...

  3. linux c开发项目过程总结

    软件工程有瀑布模型,迭代模型等. 使用linux c语言来开发项目,当然也是遵循这样的思想,先要问题定义-->需求分析--->原型设计---->编码及单元测试--->集成测试及 ...

  4. java中子类继承父类程序执行顺序

    java中子类继承父类程序执行顺序 FatherTest.java public class FatherTest { private String name; public FatherTest() ...

  5. PHP 代码编写注意事项总结归纳

    1- 编写模块化代码 良好的PHP代码应该是模块化代码.PHP的面向对象的编程功能是一些特别强大的工 具,可以把你的应用程序分解成函数或方法.你应该尽可能多的从你的应用程序的服务器端分开前端的HTML ...

  6. 【目录】mysql 进阶篇系列

    随笔分类 - mysql 进阶篇系列 mysql 开发进阶篇系列 55 权限与安全(安全事项 ) 摘要: 一. 操作系统层面安全 对于数据库来说,安全很重要,本章将从操作系统和数据库两个层面对mysq ...

  7. 从Airbnb的发展历程和网易云的大起大落看IT行业创新(第5周课后作业)

    我想先根据个人看法回答“创新是什么?”这个空泛的问题.创新是面对当下的资源条件限制创造出能够满足动态需求或解决动态发展中的问题的新策略.这种实用化定义在大部分邻域都勉强能让定义者自圆其说,对于IT行业 ...

  8. 服务器安装宝塔linux系统控制面板

    一.使用远程连接软件 (如 Putty.XShell) 连接你的Linux服务器,本教程以 Putty 为例. 1   启动 Putty.exe 程序,进入 Putty 主界面. 2  在 Host ...

  9. 使用ReadStream方法读取文件事件传递过程

    const fs = require('fs'); let file = fs.createReadStream("filename.js"); file.on("ope ...

  10. Android中App可分配内存的大小(转)

    转自:http://blog.csdn.net/u011506413/article/details/50965435 现在真实测试结果: 1,为了搞清楚每个应用程序在Android系统中最多可分配多 ...