关于LCA
题目链接:点这里
LCA最简单的思想就是暴力搜,如下:
对于每一组点u,v,求LCA(u,v)
先判断它们是否在同一深度上,不在则暴力将深度靠下的点暴力向上
然后再一同向上
但是对于上面的题一定会T了几个点
所以我们使用倍增
因为对于以上的暴力向上,我们实际上可以一次性向上走很多步,就像一步一步走和跨一大步一样
至于怎么跨一大步呢?
我们需要用到2进制了
因为对于每一个数,我们都可以用2进制表示
那么u到LCA(u,v)是不是也可以表示为2进制呢?
所以我们需要维护一个数组f[i][j]表示i节点向上走2^j次是哪一个节点
并且f[i][j] = f[f[i][j - 1]][j - 1](j == 0时f[i][j] = fa[i])
然后将他们递归到一个深度
先假设depth[u] > depth[v]
所以u要向上走k = depth[u] - depth[v]步
然后又因为k可以分解为2进制
所以你会发现u要向上走的步数从一步一步走变成了在二进制下k的每一位如果是1u = f[u][位数]
然后就是如何走到一处
我们从最大步数开始向下枚举(i)
如果f[u][i] != f[v][i]我们就让u,v分别向上走2 ^ i步
然后LCA(u,v) = f[u][0] = f[v][0]
这道题就解完了

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
int n, q;
int dep[maxn];
long long dis[maxn];
int f[maxn][30];
struct Edge{int to,weight;
};
vector<Edge> e[maxn];
void dfs(int u,int fa){f[u][0] = fa;for(int i = 1;i <= 20;i++){f[u][i] = f[f[u][i - 1]][i - 1];}for(int i = e[u].size() - 1;i >= 0;i--){int v = e[u][i].to;int w = e[u][i].weight;if(v == fa)continue;dep[v] = dep[u] + 1;dis[v] = dis[u] + w;dfs(v,u);}
}
int LCA(int u,int v){if(dep[u] < dep[v])swap(u,v);int k = dep[u] - dep[v];for(int i = 20;i >= 0;i--){if((k >> i) & 1){u = f[u][i];}}if(u == v)return u;for(int i = 20;i >= 0;i--){if(f[u][i] != f[v][i]){u = f[u][i];v = f[v][i];}}return f[u][0];
}
int main(){scanf("%d%d",&n,&q);int u, v, w;for(int i = 1;i < n;i++){scanf("%d%d%d",&u,&v,&w);e[u].push_back(Edge{v,w});e[v].push_back(Edge{u,w});}dep[1] = 0;dis[1] = 0;dfs(1,0);for(int i = 1;i <= q;i++){scanf("%d%d",&u,&v);printf("%d\n",dis[u] - 2 * dis[LCA(u,v)] + dis[v]);}return 0;
}

51nod-LCA问题_by_zyz相关推荐

  1. 51nod 2621 树上距离 (倍增+ LCA 模板)

    51nod 2621 树上距离 (倍增+ LCA 模板) 有一棵n个节点的无向树,每条边有一个边权,现在有q次询问,每次询问给出两个点,求这两个点之间的简单路径上的边权和是多少. 输入格式 第1行:两 ...

  2. [51nod] 1766树上的最远点对 树的直径 树剖LCA+ST表静态查询

    题意: 给你一棵带权树,q次查询,每次给出两个区间,[l1,r1][l2,r2][l_1,r_1] [l_2,r_2][l1​,r1​][l2​,r2​]从这两个区间中分别选择两个数字,使得这两个点的 ...

  3. 51nod1743-雪之国度【最小生成树,LCA,并查集】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1743 题目大意 nnn个点mmm条边的一张图,每次询问要求找出x,yx, ...

  4. 51NOD - 1830路径交

    题目链接:51NOD - 1830路径交 因为每次是区间询问,所以我们可以类似ST表预处理,或者线段树区间合并去处理. 每次维护节点就是代表所有路径的交集. 现在问题就是两个路径的交怎么求: 两条路径 ...

  5. 松鼠的新家 51Nod - 3116(点差分)

    https://www.51nod.com/Challenge/Problem.html#problemId=3116 题目大意:有一棵n个点的树,给出一长度为n的数组a,依次沿简单路径访问a[1], ...

  6. 【luogu3398】 仓鼠找sugar [LCA 倍增]

    P3398 仓鼠找sugar 长期不学竞赛...导致1mol的低级错误出现 把f数组开为f[N][20] 写错判断 我烂了QAQ我好瘟死于低级错误久久无法判断出来 如果两条路径相交,那么一定有一条路径 ...

  7. 51nod 1617 奇偶数组

    传送门 回来看一眼51nod,发现自己掉到rank4了,赶紧切道题回rank3. 一眼不会做,这种东西应该慢慢找规律吧--然后看到数据范围其实比较小,应该是单次log的,那是不是可以分治啊. #inc ...

  8. [BZOJ1602] [Usaco2008 Oct] 牧场行走 (LCA)

    Description N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草. 这n块土地被n-1条边连接. 奶牛可以在边上行走, ...

  9. POJ - 3694 Network tanjar割边+lca

    题目链接 思路:跑一边tanjar将所有的割边u->v标记为cut[v]=true,表示u->v这条边为割边.然后记录总的割边数ans,每次从两个询问点暴力往上边在跑直到LCA,如果碰到c ...

  10. The Shortest Statement CodeForces - 1051F LCA+最短路

    太弱了... 一开始看到题感觉是跑一个最小生成树在上边进行LCA就行了,但是发现过不了样例,然后就是就想到了之前做过类似做法的题目,就是非生成树上的边最多只有21条,然后就那些边记录下来,通过每一条边 ...

最新文章

  1. 2022-2028年中国中空玻璃聚硫密封胶行业市场研究及前瞻分析报告
  2. 假期只是玩就没意思了!告诉你一个学习麻省理工大学所有课程的好地方
  3. Ubuntu16.04安装视觉SLAM环境(OpenCV)
  4. 徒劳的对抗——如何做好极客的老婆(灵感来源于《你就是极客》)
  5. cefsharp wpf 中文输入问题解决方法
  6. 操作系统原理第十章:文件系统
  7. 反恐精英出现服务器消息,cs你已被禁用次服务器 | 手游网游页游攻略大全
  8. Mac 开发中如何设置 关闭 以及最小化 最大化按钮事件处理
  9. linux 搜索 空格,如何在Linux中搜索带有空格的模式的文件
  10. CF446D-DZY Loves Games【高斯消元,矩阵乘法】
  11. 2021高通AI应用创新大赛-创新赛道-垃圾分类识别 第三次会议研讨
  12. 基于JAVA语言的selenium测试基础总结
  13. Matlab高级教程_第一篇:Matlab基础知识提炼_02
  14. 汉诺塔函数python_Python使用函数模拟“汉诺塔”过程
  15. DSP28335代码生成——如何使用两个中断
  16. python如何设置开头注释_小疯谈python:(二)python语言的基本语法元素
  17. 句法分析(成分句法分析)(依存句法分析)
  18. CSS3选择器及优先级
  19. Java 将表格数据导入word文档中
  20. opencv中mask参数

热门文章

  1. 世界危机四伏 难道2012真的存在
  2. python爬去起点小说名以及评分
  3. AngularJs 最新验证手机号码,成功测试通过
  4. 小程序使用腾讯地图获取当前位置和地图选取位置
  5. iPhone更换字体教程,无需越狱,支持所有苹果设备!
  6. 当前计算机什么专业好就业找工作,计算机哪个专业最好就业
  7. 数据库唯一性约束(Unique Constraint)
  8. 桥接,NAT,Host Only的区别
  9. Luogu2455 [SDOI2006]线性方程组 (高斯消元)
  10. 零售药店计算机操作内容培训,零售药店gsp培训计划.doc