在dfs的过程中维护三个数组: 
deep[i],表示i点在树中的深度; 
grand[x][i],表示x的第2^i个祖先的节点编号; 
dis[x][i],表示x到它2^i祖

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int M=4e4+4;
const int maxlog=20;
struct node{
int id,val;
node(int id1=0,int val1=0):id(id1),val(val1){}
};
vector<node>e[M];
int deep[M],grand[M][maxlog],dis[M][maxlog],book[M],s,n,root;
void dfs(int x){
for(int i=1;i<=s;i++){
grand[x][i]=grand[grand[x][i-1]][i-1];//x的2^i祖先是它2^i-1祖先的2^i-1祖先
dis[x][i]=dis[x][i-1]+dis[grand[x][i-1]][i-1];//x到它2^i祖先的距离 = x到它2^i-1祖先的距离 + x的2^i-1祖先到它2^i-1祖先距离 if(!grand[x][i])//到子树跟了
break;
}
for(int i=0;i<e[x].size();i++){
int v=e[x][i].id;
if(v!=grand[x][0]){
grand[v][0]=x;维护父子关系
deep[v]=deep[x]+1;//维护深度
dis[v][0]=e[x][i].val;//维护距离
dfs(v);
}
}
}
void init(){
//n为节点个数
s=floor(log(n+0.0)/log(2.0));////最多能跳的2^i祖先
deep[0]=-1;////根结点的祖先不存在,用-1表示
dfs(root);以root为根节点建树
}
int LCA(int a,int b){
if(deep[a]>deep[b])//保证a在b上面,便于计算(floor:向下取整;ceil:向上取整)
swap(a,b);
int ans=0;
for(int i=s;i>=0;i--)//类似于二进制拆分,从大到小尝试
if(deep[a]<deep[b]&&deep[a]<=deep[grand[b][i]])//a在b下面且b向上跳后不会到a上面
ans+=dis[b][i],b=grand[b][i];//先把深度较大的b往上跳
for(int i=s;i>=0;i--)
if(grand[a][i]!=grand[b][i])//a,b的2^i祖先不一样 => 没跳到同样深度位置,接着跳
ans+=dis[a][i],a=grand[a][i],ans+=dis[b][i],b=grand[b][i];//一起往上跳
if(a!=b)//没跳到一个地方,那么再往上一个结点就是它们的LCA
ans+=dis[a][0],ans+=dis[b][0];
return ans;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int m;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
book[i]=0,e[i].clear(),deep[i]=0;
memset(grand,0,sizeof(grand));
memset(dis,0,sizeof(dis));
for(int i=1;i<n;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
book[y]=1;
e[x].push_back(node(y,w));
e[y].push_back(node(x,w));
} for(int i=1;i<=n;i++){
if(!book[i]){
root=i;
break;
}
}
init();//cout<<"!!"<<endl;
while(m--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
}
}
return 0;
}

  

先的距离。

hdu 2586 How far away ?(LCA模板)(倍增法)的更多相关文章

  1. hdu 2586(最近公共祖先LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路:在求解最近公共祖先的问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

  2. HDU 2586 How far away? LCA 转化成RMQ

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 [题意] 给出一个N 个和N-1条边的连通图,询问任意两点间的距离.N<=40000 . [分 ...

  3. 最近公共祖先(LCA)基础模板(倍增法)

    之前在澡堂学过这么个东西,听课时理解非常透彻,然后做题时是这种状态: 因为并没有切板子题,最近切掉以后看同桌,他默默地说了一句话: 我是什么时候A的来着... 我当时就心态爆炸... 现在来进行简单整 ...

  4. HDU 2586 How far away(LCA+邻接表)

    How far away &题解: 和上篇是一样的题,这用的是lca方法做的, 不知道为什么,把数组开到80000 就a了 >_< 哈 我现在知道为什么了,因为我的rmq数组没有乘 ...

  5. TTTTTTTTTTTTTTTTT HDU 2586 How far away LCA的离线算法 Tarjan

    链接: How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  6. LCA 在线倍增法 求最近公共祖先

    第一步:建树  这个就不说了 第二部:分为两步  分别是深度预处理和祖先DP预处理 DP预处理: int i,j; ;(<<j)<n;j++) ;i<n;++i) ) fa[i ...

  7. 最近公共祖先(LCA)模板

    以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖 ...

  8. 树上倍增法求LCA

    我们找的是任意两个结点的最近公共祖先, 那么我们可以考虑这么两种种情况: 1.两结点的深度相同. 2.两结点深度不同. 第一步都要转化为情况1,这种可处理的情况. 先不考虑其他, 我们思考这么一个问题 ...

  9. hdu 2586 How far away ?倍增LCA

    hdu 2586 How far away ?倍增LCA 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 针对询问次数多的时候,采取倍增 ...

  10. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

随机推荐

  1. part5 城市页面列表开发

    1.配置路由 先在router文件夹中,创建一个路由.引入组件 { path: '/city', name: 'HelloCity', component: city, meta: { name: ' ...

  2. VUE.js入门学习(1)-起步

    1.hello world <div id="app">{{content}}</div>var app = new Vue({ el:'#app', da ...

  3. 题解 Luogu P2499: [SDOI2012]象棋

    关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ...

  4. BZOJ 3197 [Sdoi2013]assassin

    题解: 树上Hash 首先重心在边上就把边分裂 以重心为根建树,这样两个根一定对应 然后f[i][j]表示i匹配另一棵的j节点的最小代价 把他们的儿子摘出来做最小权匹配即可 #include<i ...

  5. selenium登陆qq邮箱页面

    from selenium import webdriver driver = webdriver.Chrome() driver.get('https://mail.qq.com/cgi-bin/l ...

  6. Unix网络编程学习 < 一 >

    #include "unp.h" int main(int argc , char**argv) { int sockfd , n; //sockfd套接字描述符 ]; struc ...

  7. 2020 年最流行的 Java 开发技术

    不知不觉间,2020 年即将于十几天之后到来,作为技术圈中你,准备好迎接最新的变化了吗?在本文中,我们将以编程界最常用的编程语言 Java 为例,分享最为主流的技术与工具. 作者 | divyesh. ...

  8. ZJNU 2351 - 快乐

    由题意得,如果有个人从前往后能找到第一个不低于自己等级的任务,就会接取其后所有任务 那么就可以让输入数据处理成递增数列 例如1 3 5 4 6 2 7 7 3 可以处理成1 3 5 5 6 6 7 7 ...

  9. Python说文解字_main

    1. main函数: 我们知道很多的编程语言都要写一个main函数,比如在C# 中Main函数还需要大写.很多人疑惑为什么要写这么一个Main函数.其实这就是好比我们在建了一排房子,你从哪个门都可以进 ...

  10. 03 Mybatis:05.使用Mybatis完成CRUD

    mybatis框架:共四天 明确:我们在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式.不管使用XML还是注解配置. 第二天:mybatis基本使用 mybatis的单表crud操作 ...