lca

倍增求LCA模板

不想你离开。 提交于 2020-02-08 20:03:35
#include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 5; const int maxm = 1e6 + 5; struct edge { int next, v; }E[maxm]; int head[maxn]; int tot = 0; int root; void addedge(int u, int v) { E[++tot].next = head[u]; E[tot].v = v; head[u] = tot; } int dep[maxn]; int pa[maxn][25]; void dfs(int u, int depth) { dep[u] = depth; for (int i = head[u]; i; i = E[i].next) { int v = E[i].v; if (!dep[v] && v != root) { pa[v][0] = u; dfs(v, depth + 1); } } } void getparent(int n) { for (int j = 1; j <= 20; j++) { for (int i = 1; i <= n; i++) { pa[i][j] = pa[pa[i][j - 1]][j - 1]; } } } int lca

Count on a tree SPOJ - COT

回眸只為那壹抹淺笑 提交于 2020-02-08 05:12:03
题意:求树上A,B两点路径上第K小的数 AT #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<cstdlib> #include<queue> #include<set> #include<string.h> #include<vector> #include<deque> #include<map> using namespace std; #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define eps 1e-4 #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl typedef long long LL; typedef long long ll; const int maxn = 2e5 + 5; const int mod = 998244353; int n,q,m,TOT; int a[maxn],t[maxn],T[maxn],lson[maxn*30],rson[maxn*30],c[maxn*30]; void

运输计划

萝らか妹 提交于 2020-02-07 15:49:35
传送门 解法: 首先要学会求 树的最近公共祖先(LCA) 没用树剖 用了一个经常可以代替树剖的方法 树上差分 这个方法很优秀 一定要掌握 首先 有了lca 就可以求树上两点间长度 设 \(d[x]\) 为 \(x\) 到 根节点 的距离 则 \(u\) , \(v\) 间距离为 \(d[u]+d[v]-2*d[lca(u,v)]\) 同时可以实现差分 设 \(ver[x]\) 为 \(x\) 的差分数组 对于 \(u\) , \(v\) 连边 覆盖原图边的差分处理 \(ver[u]++,ver[v]++,ver[lca(u,v)]-=2\) 在进行一次dfs就求到 每个点x到父节点的边 被覆盖的次数ver[x] 二分答案 对于每个 \(u\) , \(v\) 若距离>二分的值 说明此时要在其覆盖的边中减去一条满足条件的 差分处理 设此时有cnt个路径要删边 那么能达到此时二分答案则 必须有一条边被所有路径覆盖 即dfs后 存在 \(ver[x]==cnt\) 且此时删去改边后 最长的一条路径也要不大于此时答案 此答案才可行 最后二分求出的最大可行值即为答案 代码: 第一种 倍增法求lca O(nlogn+mlogm+(n+m)logSum) 可能会被卡掉一两个点 开O2能过 #include<iostream> #include<cstdio> #include<algorithm

LCA —— 最近公共祖先

浪子不回头ぞ 提交于 2020-02-04 00:10:07
定义   给定一棵有根树,若结点 z 既是结点 x 的祖先,也是结点 y 的祖先,则称 z 是x,y的公共祖先。   在 x,y 的所有公共祖先中,深度最大的一个称为 x,y 的最近公共祖先,记为LCA(x,y)。    LCA(4 , 7) = 2,LCA(6,7) = 5 实现 暴力大法好   若求LCA(4 , 7),分别求 4 和 7 到根节点的路径。   4 -> root 的路径为:4 -> 2 -> 1。   7 -> root 的路径为:7 -> 5 -> 2 -> 1。   那么在两个路径中共有的第一个点即为答案。   所以LCA(4 , 7) = 2。   暴力大法比较简单也不怎么常用,不过多介绍。 Tarjan ST 来源: https://www.cnblogs.com/VividBinGo/p/12258091.html

【HDU5840】This world need more Zhu

可紊 提交于 2020-02-02 23:30:41
题目描述 As we all know, Zhu is the most powerful man. He has the infinite power to protest the world. We need more men like Zhu! In Duoladuo, this place is like a tree. There are \(n\) vertices and \(n−1\) edges. And the root is 1. Each vertex can reached by any other vertices. Each vertex has a people with value \(A_i\) named Zhu's believer. Liao is a curious baby, he has \(m\) questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao's questions. Liao's question will be like "u v k". That means Liao want to know the answer from following code: ans = 0; cnt = 0; for x in

Lowest Common Ancestor (LCA)

谁都会走 提交于 2020-01-31 13:03:35
题目链接 In a rooted tree, the lowest common ancestor (or LCA for short) of two vertices u and v is defined as the lowest vertex that is ancestor of both that two vertices. Given a tree of N vertices, you need to answer the question of the form " r u v " which means if the root of the tree is at r then what is LCA of u and v . Input The first line contains a single integer N . Each line in the next N - 1 lines contains a pair of integer u and v representing a edge between this two vertices. The next line contains a single integer Q which is the number of the queries. Each line in the next Q lines

PAT_A1151#LCA in a Binary Tree

大憨熊 提交于 2020-01-31 13:01:59
Source: PAT A1151 LCA in a Binary Tree (30 分) Description: The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants. Given any two nodes in a binary tree, you are supposed to find their LCA. Input Specification: Each input file contains one test case. For each case, the first line gives two positive integers: M ( ≤1,000), the number of pairs of nodes to be tested; and N ( ≤ 10,000), the number of keys in the binary tree, respectively. In each of the following two lines, N distinct integers are given as the inorder and preorder

LCA及应用

痴心易碎 提交于 2020-01-30 15:25:34
定义:   最近公共祖先简称 LCA(Lowest Common Ancestor)。两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远的那个。 性质: 1. L C A ( u ) = u LCA(u)=u L C A ( u ) = u ; 2. u u u 是 v v v 的祖先,当且仅当 L C A ( u , v ) = u LCA(u,v)=u L C A ( u , v ) = u ; 3. 如果 u u u 不为 v v v 的祖先并且 v v v 不为 u u u 的祖先,那么 u , v u,v u , v 分别处于 L C A ( u , v ) LCA(u,v) L C A ( u , v ) 的两棵不同子树中; 4. 前序遍历中, L C A ( S ) LCA(S) L C A ( S ) 出现在所有 S S S 中元素之前,后序遍历中 L C A ( S ) LCA(S) L C A ( S ) 则出现在所有 S S S 中元素之后; 5. 两点的最近公共祖先必定处在树上两点间的最短路上; 6. d ( u , v ) = h ( u ) + h ( v ) − 2 h ( L C A ( u , v ) ) d(u,v) = h(u) + h (v) - 2 h(LCA(u,v)) d ( u , v ) = h ( u ) + h ( v

Tarjan & LCA 套题题目题解

拟墨画扇 提交于 2020-01-29 17:21:42
刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 40040; const int MAXM = MAXN * 2; const int INF = 0x3f3f3f3f; struct Edge { int

LCA:Tarjan算法实现

北慕城南 提交于 2020-01-29 03:41:54
本博文转自http://www.cnblogs.com/JVxie/p/4854719.html,转载请注明出处 首先是最近公共祖先的概念(什么是最近公共祖先?):     在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点, 而最近公共祖先,就是两个节点在这棵树上 深度最大 的 公共 的 祖先节点 。     换句话说,就是两个点在这棵树上 距离最近的公共祖先节点 。     所以LCA主要是用来处理当两个点仅有 唯一一条 确定的最短路径时的路径。     有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢?     答案是肯定的,很简单,按照人的亲戚观念来说, 你的父亲也是你的祖先 ,而LCA还可以 将自己视为祖先节点 。     举个例子吧,如下图所示 4 和 5 的 最近公共祖先是2 , 5 和 3 的 最近公共祖先 是 1 , 2 和 1 的 最近公共祖先 是 1 。      这就是最近公共祖先的基本概念了,那么我们该如何去求这个最近公共祖先呢?     通常初学者都会想到最简单粗暴的一个办法:对于每个询问,遍历所有的点,时间复杂度为 O(n*q) ,很明显, n和q一般不会很小 。     常用的求LCA的算法有:Tarjan/DFS+ST/倍增     后两个算法都是在线算法,也很相似,时间复杂度在 O(logn) ~ O(nlogn) 之间