在 x,y 的所有共公共祖先中,深度最大的一个称为 x,y 的最近公共祖先,记为 LCA(x,y)。 LCA(x,y) 是 x 到根的路径与 y 到根的路径的交汇点,它也是 x 与 y 之间的路径上深度最小的节点。 这里着重介绍树上倍增法求LCA。 树上倍增法是一个很重要的算法。除了求 LCA 之外,它在很多问题中都有广泛...
nowcoder172C 保护 (倍增lca+dfs序+主席树) https://www.nowcoder.com/acm/contest/172/C (sbw大佬太强啦 orz) 先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对于某两个(直上直下的)路径a,b,b的下端点在a的下端点子树中,且b的上端点深度<=a的上端点深度,那么b是覆盖a的。
1.树上倍增 #include <queue> #include <cstdio> using namespace std; const int MAXN = 1e5 + 5; const int MAXTEP = 45; int n, m; int depth[MAXN],
跑半遍LCA,到他俩深度相同的时候停止。然后判断是否在同一条链上,分别返回不同的答案就行了。注意在同一条链的时候,不能用u和v的,需要用u(深度大的)的和对应链上dep[v]+1的那个点的。(来看几发错误代码) 错误代码1: #include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include ...
通过保留关键点的lca,我们可以尽可能地做到使虚树结构与原树相似,这样便使得我们的转化是有效的。 三、建立过程 1. 初始化 初始化ST表并将关键点按照Dfs序排序。 2. 得到虚树上的点 利用倍增求出排好序过后的关键点相邻两点的LCA,并加入关键点数组中,重新按照Dfs序排序并去重。
inline int lca(int a,int b) { if(dep[a] > dep[b]) swap(a,b); if(dep[a] != dep[b]) { for(int i = logn;i >= 0;--i) if(dep[F[i][b]] >= dep[a]) b = F[i][b]; } if(a == b) return a; for(int i = logn; i >= 0; --i) ...
我们考虑用dfs来处理,后面寻路的时候采用倍增法求LCA,看到零食最大也就很容易想到状态压缩,所以我们的目标就是到与到的零食之和,我们可以开数组来帮助我们进行最多次的跳转,然后通过公共祖先来解决这个问题。 //考场上的30分题解#include <bits/stdc++.h>#define IOS ios::sync_with_stdio(0), cin.tie(0)#...
本题就是一道LCA的模板题, 使用倍增法或者tarjan算法都是可以。 距离可能会爆int, 因此建议是所有整型都用long long。 #include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;using ll = long long;vector<pair<int, int>> g[N];ll dep[N], f[N][30], dist[N];//倍增LCA预处...
:star2: Wiki of OI / ICPC for everyone. (某大型游戏线上攻略,内含炫酷算术魔法) - OI-wiki/docs/graph/lca.md at 08ab166c76bbce2b4c7bd95a2e47a2c85032dc3b · yyyu-star/OI-wiki
http://codeforces.com/contest/1328/problem/E 题意: 一棵树,有m个询问,每次询问询问k个点是否都在一条从根节点(点1)到某个节点v的路径上,或者距离这条路径的距离为1也可以。 首先先解决判断所给的点是否都在一条从根节点到某个点的路径上这个问题: 可以参考倍增求lca的方法,判断某个点是否为另外一个点...