LCA倍增【模板】

 1 #include <algorithm>
 2 #include <cstdio>
 3 #include <vector>
 4
 5 #define N 10015
 6
 7 using namespace std;
 8
 9 vector<int>vec[N];
10 int n,a,b,m,deep[N],dad[N][100];
11
12 int LCA(int x,int y)
13 {
14     if(deep[x]>deep[y]) swap(x,y);
15     for(int i=20;i>=0;i--)
16         if(deep[dad[y][i]]>=deep[x]) y=dad[y][i];
17     if(x==y) return x;
18     for(int i=20;i>=0;i--)
19         if(dad[x][i]!=dad[y][i])
20         x=dad[x][i],y=dad[y][i];
21     return dad[x][0];
22 }
23
24 void DFS(int x)
25 {
26     deep[x]=deep[dad[x][0]]+1;
27     for(int i=0;dad[x][i];i++)
28         dad[x][i+1]=dad[dad[x][i]][i];
29     for(int i=0;i<vec[x].size();i++)
30         if(!deep[vec[x][i]]) dad[vec[x][i]][0]=x,DFS(vec[x][i]);
31 }
32
33 int main()
34 {
35     scanf("%d",&n);
36     for(int i=1;i<n;i++)
37     {
38         scanf("%d%d",&a,&b);
39         vec[a].push_back(b);
40         vec[b].push_back(a);
41     }
42     DFS(1);
43     scanf("%d",&m);
44     while(m--)
45     {
46         scanf("%d%d",&a,&b);
47         printf("%d\n",LCA(a,b));
48     }
49     return 0;
50 }
51 /*
52 6
53 1 2
54 1 3
55 4 2
56 5 2
57 3 6
58 5
59 4 5
60 2 6
61 3 6
62 1 5
63 4 6
64 */
时间: 2024-08-24 11:28:41

LCA倍增【模板】的相关文章

LCA倍增算法

LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 4 组合得到 便于读者理解 我放一道例题吧 Problem F: 挑战迷宫 Description 小翔和小明正在挑战一个神奇的迷宫.迷宫由n个房间组成,每个房间的编号为1~n,其中1号房间是他们俩初始位置, 所有房间一共由n-1条路连接,使得房间两两之间能够相互达到(构成一棵树),每条路的长度为W

LCA(倍增在线算法) codevs 2370 小机房的树

codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计

codeforces 587C:(LCA倍增+维护最小值)

一开始直接无脑tarjan,回溯只能一层层往上走,太慢了,加了各种优化还是TLE 后来了解到LCA倍增法(在线).复杂度其实相比LCA转RMQ以及tarjan是要稍差一些,但是其中能同步维护的只有LCA倍增,很神奇的算法 #include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include&q

UVa 11354 Bond 最小生成树+LCA倍增

题目来源:UVa 11354 Bond 题意:n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小 思路:使最大的危险系数尽量小 答案是最小生成树上的边 然后用LCA倍增法记录s和t到他们最近公共祖先的最大值 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50010; const int INF =

URAL 1752. Tree 2 树的直径+LCA倍增

题目来源:URAL 1752. Tree 2 题意:求一个点v与它距离为d的任意一个点 没有输出0 思路:开始想倍增法 但是倍增法只能往他的祖先去 后来百度发现了树的直径 想了想 发现可以建2棵树 每一棵树的根是树的直径的2个端点 这样保证了每个点和他距离最远的点就是其中一个根 因为一个点到树的直径的端点的距离是最远的 最后就是LCA倍增了 #include <cstdio> #include <cstring> #include <algorithm> #includ

HDU 4547 LCA倍增算法

CD操作 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1111    Accepted Submission(s): 297 Problem Description 在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录. 这里我们简化一下问题,假设只有一个根目录,

次小生成树(LCA倍增)

算法: 求出MST之后枚举每条在MST之外的边 连上之后会出现环 找到环中除加上的边之外权值最大的边 删除该边之后得到一颗新树 做法: 利用LCA倍增地维护最小生成树上两点之间的最大边权 每次枚举在MST之外的边 有两种情况 ①.两个端点在一条链上 ②.两个端点不在一条链上 第一种情况就直接得到答案 第二种情况的话分两步处理取MAX 复杂度mlogn 严格 bzoj1977 严格的话不仅要处理出maxe[i][j]还要处理出次大的maxe2[i][j] 因为当两点之间的边权最大值等于加上的边权的

洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)

构建完MST后,枚举非树边(u,v,w),在树上u->v的路径中找一条权值最大的边(权为maxn),替换掉它这样在 w=maxn 时显然不能满足严格次小.但是这个w可以替换掉树上严格小于maxn的次大边用倍增维护MST上路径的最大值.次大值,每条非树边的查询复杂度就为O(logn) ps:1.倍增更新次大值时,未必是从最大值转移,要先赋值较大的次大值,再与较小的那个最大值比较.2.maxn!=w时,是可以从maxn更新的(不能更新就是上面情况啊)倍增处理部分我还是在dfs里写吧 md改了一晚上

求lca(模板)

洛谷——P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样