在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;
}

  

先的距离。

最新文章

  1. PHP之compact()函数
  2. 做 Web 开发少不了这些的
  3. nginx入门篇----安装、部署、升级
  4. tengine-2.1.0 + lua + base64
  5. [USACO2004][poj1989]The Cow Lineup(乱搞)
  6. Provisioning Profile
  7. 文本去重之MinHash算法
  8. 手把手教你如何搭建iOS项目基本框架
  9. windows 创建服务提示失败 5 拒绝 访问拒绝
  10. TCL_事务控制语言
  11. Android开发之Action Bar
  12. 如何在Elasticsearch中安装中文分词器(IK)和拼音分词器?
  13. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (一)
  14. 小程序Promise不支持finally解决方案
  15. 使用Google cardboard 2的一些软件
  16. SDN 交换机迁移1
  17. &lt;转&gt;Python: __init__.py 用法
  18. iddea代码调试debug篇
  19. BZOJ3512 DZY Loves Math IV(杜教筛+线性筛)
  20. java分布式集群

热门文章

  1. python try-except处理异常的常用方法分析
  2. 吴裕雄--天生自然TensorFlow2教程:Broadcasting
  3. 吴裕雄--天生自然 JAVASCRIPT开发学习:计时事件
  4. 吴裕雄--天生自然 JAVASCRIPT开发学习:Window - 浏览器对象模型
  5. jstl中遍历Map
  6. python画图嵌入html
  7. proto3 不支持内建类型的非空判断即 hasXXX
  8. python 常用函数用法
  9. Lambder笔记
  10. 多线程下,两个线程交替打印0 -100,使用wait()和notify()