How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10764    Accepted Submission(s): 3923

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
 
 
这题可以用离线算法做,我这里介绍的是RMQ算法 。。
RMQ算法就是求区间最值问题的算法,这里用到最近公共祖先上面。是根据每个点的编号以及深度来确定最近公共祖先。
贴模板:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define N 40010
#define M 205 struct Edge{
int u,v,w,next;
}e[*N];
int head[N];
int dp[*N][]; ///
int vis[N];
int first[N];
int deep[*N]; ///记录每个点每次出现出现所在的深度,由于回溯,遂开两倍
int id[*N]; ///结点的编号,也会出现两次
int dis[N];
int tot; int MIN(int i,int j){
if(i>=j) return j;
return i;
}
void add_edge(int u,int v,int w,int & k){
e[k].u=u;e[k].v=v;e[k].w = w;
e[k].next=head[u];head[u]=k++;
}
void dfs(int u,int d){
vis[u]=true;id[++tot]=u;first[u]=tot;deep[tot]=d;
for(int k = head[u];k!=-;k=e[k].next){
if(!vis[e[k].v]){
int v = e[k].v,w = e[k].w;
dis[v]=dis[u]+w;
dfs(v,d+);
id[++tot]=u,deep[tot]=d;
}
}
}
void init_RMQ(int n){
for(int i=;i<=n;i++){
dp[i][]=i; ///保存的是下标
}
for(int j=;(<<j)<=n;j++){
for(int i=;i+(<<j)-<n;i++){
dp[i][j] = MIN(dp[i][j-],dp[i+(<<(j-))][j-]);
}
}
}
int RMQ(int L,int R){
int k=;
while((<<(k+))<=(R-L+)) k++;
int a = dp[L][k],b = dp[R-(<<k)+][k];
if(deep[a]<deep[b]) return a;
return b;
}
int LCA(int L,int R){
int x = first[L];
int y = first[R];
if(x>y) swap(x,y);
return id[RMQ(x,y)];
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--){
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
int n,m;
scanf("%d%d",&n,&m);
tot = ;
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w,tot);
add_edge(v,u,w,tot);
}
tot = ;
dis[]=;
dfs(,);
init_RMQ(*n-);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
int lca = LCA(a,b);
printf("%d\n",dis[a]+dis[b]-*dis[lca]);
}
}
return ;
}

LCA上的RMQ模板算法的更多相关文章

  1. ST(RMQ)算法(在线)求LCA

    在此之前,我写过另一篇博客,是倍增(在线)求LCA.有兴趣的同学可以去看一看.概念以及各种暴力就不在这里说了,那篇博客已经有介绍了. 不会ST算法的同学点这里 ST(RMQ)算法在线求LCA 这个算法 ...

  2. 求解区间最值 - RMQ - ST 算法介绍

    解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...

  3. LCA最近公共祖先模板(求树上任意两个节点的最短距离 || 求两个点的路进(有且只有唯一的一条))

    原理可以参考大神 LCA_Tarjan (离线) TarjanTarjan 算法求 LCA 的时间复杂度为 O(n+q) ,是一种离线算法,要用到并查集.(注:这里的复杂度其实应该不是 O(n+q)  ...

  4. Poj 3264 Balanced Lineup RMQ模板

    题目链接: Poj 3264 Balanced Lineup 题目描述: 给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值. 解题思路: 很模板的RMQ模板题,在这 ...

  5. SMW0上传EXCEL模板时报错无分配给对象***的MIME类型

    在使用SMW0上传照片.声音文件.EXCEL模板等文件时,遇到报错提示,如下图所示: 解决办法:需要先维护 .XLS 文件的MIME TYPE,SMW0 打开如下图所示 选择上图红色框中“WebRFC ...

  6. LCA转换成RMQ

    LCA(Lowest Common Ancestor 最近公共祖先)定义如下:在一棵树中两个节点的LCA为这两个节点所有的公共祖先中深度最大的节点. 比如这棵树 结点5和6的LCA是2,12和7的LC ...

  7. 在 iPad 上试验从用算法生成法线贴图-到法线映射光照效果

    在 iPad 上试验从用算法生成法线贴图-到法线映射光照效果 目录 概述 一般来说, 法线贴图是用高模的法线图, 低模的纹理图, 来生成较好的渲染效果. 而法线图通常是通过图像处理软件来生成的, 这里 ...

  8. Zeratul的完美区间(线段树||RMQ模板题)

    原题大意:原题链接 给定元素无重复数组,查询给定区间内元素是否连续 解体思路:由于无重复元素,所以如果区间内元素连续,则该区间内的最大值和最小值之差应该等于区间长度(r-l) 解法一:线段树(模板题) ...

  9. 模板—算法—整体二分(区间k小值)

    模板—算法—整体二分(区间k小值) Code: #include <cstdio> #include <algorithm> using namespace std; #def ...

随机推荐

  1. PHP导出excel,无乱码

    php部分 header("Content-type:application/octet-stream"); header("Accept-Ranges:bytes&qu ...

  2. RobHess的SIFT源码分析:imgfeatures.h和imgfeatures.c文件

    SIFT源码分析系列文章的索引在这里:RobHess的SIFT源码分析:综述 imgfeatures.h中有SIFT特征点结构struct feature的定义,除此之外还有一些特征点的导入导出以及特 ...

  3. Codeforces Round #508 (Div. 2) E. Maximum Matching(欧拉路径)

     E. Maximum Matching 题目链接:https://codeforces.com/contest/1038/problem/E 题意: 给出n个项链,每条项链左边和右边都有一种颜色(范 ...

  4. 使用html5的Geolocation API实现定位

    公司有个需求,需要获取用户的位置,所以看了下html5的Geolocation 这个新东西,发现挺好用的. <!DOCTYPE html> <html> <body> ...

  5. 剑指offer --合并链表

    题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解法://递归解法 public class MixLink { /* public class L ...

  6. ZJOI2002 昂贵的聘礼

    题目描述 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请 ...

  7. 2015/8/31 Python基础(5):字符串

    字符串是Python最常见的一种类型.通过在引号间包含字符的方式创建它.Python里单双引号的作用是一致的.Python的对象类型里不存在字符型,一般用单个字符的字符串来使用.Python的字符串是 ...

  8. Linux系统文件权限体系详解

    准备工作:先简单了解Linux文件权限 在Linux系统中,ls -l 命令可以查看文件的权限,如 [zhaohuizhen@localhost Test]$ ls -l a -rw-rw-r--. ...

  9. HDU 1574 RP问题 (dp)

    题目链接 Problem Description 在人类社会中,任何个体都具有人品,人品有各种不同的形式,可以从一种形式转换为另一种形式,从一个个体传递给另一个个体,在转换和传递的过程中,人品不会消失 ...

  10. jQuery右侧悬浮楼层滚动 电梯菜单

    http://www.kaiu.net/effectCon.aspx?id=2198 <!doctype html> <html> <head> <meta ...