Tarjan 算法求 LCA / Tarjan 算法求强连通分量
- 【时光蒸汽喵带你做专题】最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
- tarjan LCA - YouTube
- Tarjan算法_LCA - A_Bo的博客 - CSDN博客
- Tarjan离线算法求最近公共祖先(LCA) - 初学者 - CSDN博客
- 最近公共祖先(LCA) - riteme.site
- Fuzhou University OnlineJudge 1628
- P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态
- 有向图强连通分量的Tarjan算法 - BYVoid
- Tarjan算法 详解+心得 - Christopher_Yan - 博客园
- UESTCACM 每周算法讲堂第25期 Tarjan求强连通分量_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
洛谷P3379 【模板】最近公共祖先(LCA)
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <set>
#include <stack>
#include <map>
#include<vector>
using namespace std;
const int maxn = 5e5 + 5;
struct query
{
int x;
int y;
int lca;
}query[maxn];
int fa[maxn];
bool vis[maxn];
int deep[maxn];
vector<int> G[maxn];
vector<int> Q[maxn];
void init()
{
for (int i = 0; i < maxn; i++)
{
fa[i] = i;
}
}
int find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void Union(int v, int u)
{
int vfa = find(v), ufa = find(u);
if (vfa == ufa)return;
else fa[v] = u;
}
void tarjan(int u)
{
vis[u] = true;
for (auto qid : Q[u]) {
if (query[qid].x == u) {
if (vis[query[qid].y]) {
query[qid].lca = find(query[qid].y);
}
}
else
{
if (vis[query[qid].x]) {
query[qid].lca = find(query[qid].x);
}
}
}
for (auto v : G[u]) {
if (vis[v])
continue;
deep[v] = deep[u] + 1;
tarjan(v);
Union(v, u);
}
}
int main()
{
init();
int n, m, s;
scanf_s("%d%d%d", &n, &m, &s);
int x, y;
for (int i = 1; i < n; i++)
{
scanf_s("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
for (int i = 1; i <= m; i++)
{
scanf_s("%d%d", &query[i].x, &query[i].y);
Q[query[i].x].push_back(i); // 对于节点 x 来说有一个编号为 i 的询问
Q[query[i].y].push_back(i);
}
tarjan(s);
for (int i = 1; i <= m; i++)
{
printf("%d\n", query[i].lca);
}
for (int i = 1; i <= n; i++)
{
printf("节点 %d 的深度是 %d\n", i, deep[i]);
}
}
FOJ 1628 计算公共祖先的个数
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <set>
#include <stack>
#include <map>
#include<vector>
using namespace std;
const int maxn = 5e5 + 5;
struct query
{
int x;
int y;
int lca;
}query[maxn];
int fa[maxn];
bool vis[maxn];
int deep[maxn];
vector<int> G[maxn];
vector<int> Q[maxn];
void init()
{
deep[1] = 1;
for (int i = 0; i < maxn; i++)
{
fa[i] = i;
}
}
int find(int x)
{
if (fa[x] == x)
return x;
else
return fa[x] = find(fa[x]);
}
void Union(int v, int u)
{
int vfa = find(v), ufa = find(u);
if (vfa == ufa)return;
else fa[v] = u;
}
void tarjan(int u)
{
for (int i = 0; i < Q[u].size(); i++) {
if (query[Q[u][i]].x == u) {
if (vis[query[Q[u][i]].y]) {
query[Q[u][i]].lca = find(query[Q[u][i]].y);
}
}
else
{
if (vis[query[Q[u][i]].x]) {
query[Q[u][i]].lca = find(query[Q[u][i]].x);
}
}
}
vis[u] = true;
for (int i = 0; i < G[u].size(); i++) {
if (vis[G[u][i]])
continue;
deep[G[u][i]] = deep[u] + 1;
tarjan(G[u][i]);
Union(G[u][i], u);
}
}
int main()
{
init();
int n, k, m;
int x, y;
scanf_s("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &k);
for (int j = 1; j <= k; j++)
{
scanf_s("%d", &y);
G[i].push_back(y);
G[y].push_back(i);
}
}
scanf_s("%d", &m);
for (int i = 1; i <= m; i++) // 离线处理
{
scanf_s("%d%d", &query[i].x, &query[i].y);
Q[query[i].x].push_back(i); // 对于节点 x 来说有一个编号为 i 的询问
Q[query[i].y].push_back(i);
}
tarjan(1);
/*for (int i = 1; i <= m; i++)
{
printf("%d\n", query[i].lca);
}
for (int i = 1; i <= n; i++)
{
printf("节点 %d 的深度是 %d\n", i, deep[i]);
}*/
for (int i = 1; i <= m; i++)
{
printf("%d\n", deep[query[i].lca]);
}
}
Tarjan 算法求 LCA / Tarjan 算法求强连通分量的更多相关文章
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】
一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...
- (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
- SPOJ 10628 Count on a tree(Tarjan离线 | RMQ-ST在线求LCA+主席树求树上第K小)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
- 算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法
强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...
- HDU-2874-森林求LCA/tarjan
http://acm.hdu.edu.cn/showproblem.php?pid=2874 给出一个森林,询问任意两点最短距离. tarjan跑一遍即可,就是这个题卡内存,vector会MLE,换前 ...
- 算法笔记--lca倍增算法
算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; ][N]; int deep[N]; int h[N]; void dfs(int ...
- Tarjan算法初探 (1):Tarjan如何求有向图的强连通分量
在此大概讲一下初学Tarjan算法的领悟( QwQ) Tarjan算法 是图论的非常经典的算法 可以用来寻找有向图中的强连通分量 与此同时也可以通过寻找图中的强连通分量来进行缩点 首先给出强连通分量的 ...
- 求LCA最近公共祖先的离线Tarjan算法_C++
这个Tarjan算法是求LCA的算法,不是那个强连通图的 它是 离线 算法,时间复杂度是 O(m+n),m 是询问数,n 是节点数 它的优点是比在线算法好写很多 不过有些题目是强制在线的,此类离线算法 ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
随机推荐
- Zookeeper到底是什么
1. 什么是Zookeeper 用一句话对其进行定义就是:它是一套高吞吐的分布式协调系统.从中我们可以知道Zookeeper至少具有以下特点: 1.Zookeeper的主要作用是为分布式系统提供协调服 ...
- RabbitMQ消息中间件的用法
1.什么是RabbitMQ RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消 ...
- WebUploader 上传文件 错误总结
近日做文件上传,粗心的问题和技术不精的问题导致了很多的bug,大部分时间都是在找自己写出来的bug,近日总结一下使用 WebUploader 开启分片上传的使用方法以及注意事项 1.上传过程中,后续上 ...
- beyond compare全文件夹比较,仅显示变化的文件
beyond compare是一款非常优秀的文件夹同步比较工具,赞. 非常强大的一点就是给定两个文件夹可以自动列出所有不同的文件和子文件夹,但是有一点可能很多人碰到过,也就是需要一个个点开才能重新比 ...
- 消息队列mq总结
一.消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有ActiveMQ,RabbitM ...
- WIN10 报错 "此共享需要过时的SMB1协议,而此协议是不安全"的解决方法
发现新安装的win10能看到其他计算机,但不能共享其他计算的共享文件/夹,出现如下情况:在浏览器里输入:\IP 不能访问到计算机的共享文件夹,或者在桌面上新建一个指向到其他计算机共享文件/夹的快捷方式 ...
- vue-cli随机生成port源码
const portfinder = require('portfinder'): const port = await portfinder.getPortPromise(): 两行代码 端口搜索范 ...
- 隐马尔科夫模型(Hidden Markov Models) 系列之一
转自:http://blog.csdn.net/eaglex/article/details/6376826 介绍(introduction) 通常我们总是对寻找某一段时间上的模式感兴趣,这些模式可能 ...
- Java集合学习(9):集合对比
一.HashMap与HashTable的区别 HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.Hash ...
- HLOJ1361 Walking on the Grid II 矩阵快速幂
题目分析: 就当是一次记录吧,2013年绍兴市市赛的一题,重现赛当时我想递推可能是矩阵快速幂吧,但是这个递推公式真没推出来(赛后猛如虎系列),这题和第一题有联系又有区别,第一题的递推很简单,dp[i] ...