当前位置:网站首页>最近公共祖先离线做法(tarjan)
最近公共祖先离线做法(tarjan)
2022-07-01 19:36:00 【Zqchang】
在线离线
在线和离线一般是针对有询问的题目
在线做法:就是每读入一个询问,就可以立即算一个答案,然后输出
离线做法:我们必须先把所有询问统一读进来,然后统一计算完之后,再把所有询问统一输出
tarjan O(n + m)
n是节点数量,m是询问数量
本质是对向上标记法的优化
向上标记法
具体可看上一个在线做法
在深度优先遍历过程中把所有点分为三大类
1.已经遍历过,且回溯过的点,被搜过,而且子树被搜完
2.正在搜索的分支
3.还未搜索到的点
假设是从左往右搜索,就形成了这样的一棵树绿色是第一种,红色是第二种,也就是一个路径,其他的是第三种

对于正在搜索的点,我们找一下与之相关的询问,由上图可以发现,当前询问的点x和绿色部分的公共祖先都是路径总的点,因为可以将路径中点的子树合并到该点中去,最后求公共祖先的时候,就是看一下那个点被合并到哪个点去了,可以用并查集来实现,这就是找祖宗节点
这样,每个点只会被遍历一次,也只会被合并一次,对于每个查询也只会查询一次
主要思想
我们在遍历当前这个分支的时候,对于所有和这个点相关的节点的公共祖先,我们可以发现,如果这个点已经被遍历过了的话,所在整个子树的公共祖先都是路径中的那个点,也就是该子树的根节点,也就是每次遍历完一个点之后,就可以把当前这个点直接合并到根节点当中去,当我们查询的时候,就可以直接在并查集里面查当前元素的代表元素是谁,这个代表元素就是它的公共祖先
这个要注意什么时候合并,就是要在回溯完之后,再把它合并到父节点中
例题
距离
题意就是要求两个点之间的距离
方法如图,都算出来到根节点的距离,再减去两倍的公共祖先的距离
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define PII pair<int, int>
const int N = 1e4 + 10;
#define x first
#define y second
vector<PII> v[N];
int n, m, a, b, k;
int dist[N];//存储每个点到根节点距离
int p[N];
int res[N * 2];// 存答案
int st[N];
vector<PII> query[N]; // first存查询的另外一个点,second存查询编号
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void dfs(int u, int fa)
{
for(auto i : v[u])
{
if(i.x == fa) continue;
dist[i.x] = dist[u] + i.y;
dfs(i.x, u);
}
}
void tarjan(int u)
{
st[u] = 1;
for(auto i : v[u])
{
if(!st[i.x])
{
tarjan(i.x);
p[i.x] = u;
}
}
for(auto i : query[u])
{
if(st[i.x] == 2)//查看另一个点是不是回溯过了,如果没回溯过就跳
{
int anc = find(i.x);
res[i.y] = dist[u] + dist[i.x] - dist[anc] * 2;
}
}
st[u] = 2;
}
signed main()
{
cin >> n >> m;
for(int i=1; i<=n-1; i++)
{
cin >> a >> b >> k;
v[a].push_back({
b, k});
v[b].push_back({
a, k});
}
for(int i=1; i<=m; i++)
{
cin >> a >> b;
if(a != b)
{
query[a].push_back({
b, i});
query[b].push_back({
a, i});
}
}
for(int i=1; i<=n; i++) p[i] = i;
dfs(1, -1);
tarjan(1);
for(int i=1; i<=m; i++) cout << res[i] << endl;
return 0;
}
边栏推荐
猜你喜欢

芭比Q了!新上架的游戏APP,咋分析?

新牛牛盲盒微信小程序源码_支持流量变现,带完整素材图片

300题线性代数 第四讲 线性方程组

深度学习 常见的损失函数

How to connect the two nodes of the flow chart

Develop those things: easycvr cluster device management page function display optimization

Big factories are wolves, small factories are dogs?
![[multithreading] realize the singleton mode (hungry and lazy) realize the thread safe singleton mode (double validation lock)](/img/bf/524e78473625a31c024783ccec8d46.png)
[multithreading] realize the singleton mode (hungry and lazy) realize the thread safe singleton mode (double validation lock)

运动捕捉系统原理

编译原理复习笔记
随机推荐
2022年高处安装、维护、拆除考题模拟考试平台操作
股票手机开户哪个app好,安全性较高的
如何用OpenMesh创建一个四棱锥
薛定谔的日语学习小程序源码
新版Free手机、PC、平板、笔记本四端网站缩略展示图在线一键生成网站源码
What if the win11 shortcut key switching input method doesn't respond? Shortcut key switching input method does not respond
从20s优化到500ms,我用了这三招
Principle of motion capture system
After adding cocoapods successfully, the header file cannot be imported or an error is reported in not found file
Halcon知识:三维重构的一个尝试
多个张量与多个卷积核做卷积运算的输出结果
【opencv】train&test HOG+SVM
Keras machine translation practice
人才近悦远来,望城区夯实“强省会”智力底座
2022安全员-A证考题及在线模拟考试
300 linear algebra Lecture 4 linear equations
大厂做狼,小厂做狗?
Niuke programming question -- must brush the string of 101 (brush the question efficiently, draw inferences from one instance)
关联线探究,如何连接流程图的两个节点
Optimization of the problem that the request flow fails to terminate during page switching of easycvr cluster video Plaza