Tarjan打包总结(求强连通分量、割点和Tarjan-LCA)

写给自己的Tarjan算法总结,包括求强连通分量、割点和Tarjan-LCA,基础概念就没有废话了,只写自己的理解和板子

强连通分量&缩点

原理

在DFS生成树中,如果一个节点通过其所有子节点的返祖边恰能达到这个节点,那么这些满足条件的点中最高的那个节点一定是强连通分量

伪代码

tarjan(u)
{
DFN[u]=Low[u]=++Index // 为节点u设定次序编号和Low初值
Stack.push(u) // 将节点u压入栈中
for each (u, v) in E // 枚举每一条边
if (v is not visted) // 如果节点v未被访问过
tarjan(v) // 继续向下找
Low[u] = min(Low[u], Low[v])
else if (v in S) // 如果节点v还在栈内
Low[u] = min(Low[u], DFN[v])
if (DFN[u] == Low[u]) // 如果节点u是强连通分量的根
repeat
v = S.pop // 将v退栈,为该强连通分量中一个顶点
print v
until (u== v)
}

板子(C++)

void tarjan(int u){
dfn[u]=++cnt;
low[u]=cnt;
ins[u]=1;
s[++top]=u;
for(register int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(dfn[v]==0){
tarjan(v);
low[u]=MIN(low[u],low[v]);
}else if(ins[v])
low[u]=MIN(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
ins[u]=0;
while(s[top]!=u){
//do something
ins[s[top]]=0;
top--;
}
top--;
}
}

割点

原理

思路同上,如果一个节点不为根节点且只要有一个子节点通过返祖边不能到达这个节点的祖先节点,那么这个节点就一定是一个割点。而如果这个节点是个根节点的话,只要其子树数大于1就一定是个割点了。

例如下图中,1和2就是割点

dfs生成树:

实边为树边,虚线为返祖边

伪代码

tarjan(u, fa){
dfn[u]=low[u]=++index // 为节点u设定次序编号和Low初值
int cnt=0; //统计子节点个数
for each (u, v) in E // 枚举每一条边
cnt++;
if (v is not visted) // 如果节点v未被访问过
tarjan(v);
low[u]=min(low[u], low[v]);
if(u is root and cnt>1) //如果当前节点是根节点且其子树数大于1
ans[u]=1; //那么节点u就是一个割点
else if(low[v]>=dfn[u]) //如果有一个子节点v通过返祖边不能到达这个节点的祖先节点
ans[u]=1; //那么节点u就是一个割点
else if(v!=fa) //必须确保节点不为其父亲,否则会陷入死循环
low[u]=min(low[u], low[v]);
}

最近公共祖先(LCA)

原理

因为DFS遍历的性质,所以任意一对询问第一次都已经被访问到时,此时在已经访问过的最低且度不为0的节点就是这次询问的公共祖先(其实另外一个doubly在线算法也是利用了DFS遍历的性质,异曲同工之妙)

伪代码

tarjan-lca(u)//marge和find为并查集合并函数和查找函数
{
for each(u,v) //访问所有u子节点v
{
Tarjan(v); //继续往下遍历
marge(u,v); //合并v到u上
标记v被访问过;
}
for each(u,e) //访问所有和u有询问关系的e
{
如果e被访问过;
u,e的最近公共祖先为find(e);
}
}

板子

void tarjan-lca(int u, int fa){
fa[u]=u;//并查集初始化
for(register int i=0;i<e[u].size();i++){
int v=e[u][i];
if(v==fa) continue;
Tarjan(v);
fa[v]=u;//merge
}
for(register int i=0;i<q[u].size();i++){
int v=q[u][i].data;
if(fa[v]) ans[q[u][i].id]=find(v);
}
}

本文采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处: 转载自:Santiego的博客

Tarjan算法打包总结(求强连通分量、割点和Tarjan-LCA)的更多相关文章

  1. 求强连通分量模板(tarjan算法)

    关于如何求强连通分量的知识请戳 https://www.byvoid.com/blog/scc-tarjan/ void DFS(int x) { dfn[x]=lowlink[x]=++dfn_cl ...

  2. 模板 - 强连通分量/割点/桥 - Tarjan

    int dfn[N], low[N], dfncnt, s[N], tp; int scc[N], sc; // 结点 i 所在 scc 的编号 int sz[N]; // 强连通 i 的大小 voi ...

  3. Tarjan求强连通分量,缩点,割点

    Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...

  4. tarjan算法-解决有向图中求强连通分量的利器

    小引 看到这个名词-tarjan,大家首先想到的肯定是又是一个以外国人名字命名的算法.说实话真的是很佩服那些算法大牛们,佩服得简直是五体投地啊.今天就遇到一道与求解有向图中强连通分量的问题,我的思路就 ...

  5. Tarjan求强连通分量、求桥和割点模板

    Tarjan 求强连通分量模板.参考博客 #include<stdio.h> #include<stack> #include<algorithm> using n ...

  6. tarjan求强连通分量+缩点+割点以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  7. tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  8. Tarjan 算法求 LCA / Tarjan 算法求强连通分量

    [时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...

  9. 【学习整理】Tarjan:强连通分量+割点+割边

    Tarjan求强连通分量 在一个有向图中,如果某两点间都有互相到达的路径,那么称中两个点强联通,如果任意两点都强联通,那么称这个图为强联通图:一个有向图的极大强联通子图称为强联通分量.   算法可以在 ...

随机推荐

  1. PHP格式化(文件)存储数据大小(SIZE)显示

    有时候我们需要在网页上显示某个文件的大小,或者是其它数据的大小数字. 这个数字往往从跨度很大,如果以B为单位的话可能是个位,如果1G则长达1073741824的数字,这个时候我们就需要根据大小来格式化 ...

  2. Fedora 16下安装ruby on rails

    Fedora 16下安装ruby on rails 最近在windows下写了些rails小程序,问题一个接一个,到最后终于坚信了那句话“windows不适合用于ruby on rails开发”.于是 ...

  3. 认识Filter

    1). Filter 是什么 ? ①. JavaWEB 的一个重要组件, 可以对发送到 Servlet 的请求进行拦截, 并对响应也进行拦截. ②. Filter 是实现了 Filter 接口的 Ja ...

  4. JavaScript -- Array中的push()方法和concat()方法介绍

    Array => push()方法向数组的末尾添加一个或者多个元素,也就是说它会改变数组本身 concat() => concat()方法用于连接2个或者多个数组,但它的特殊之处在于,它会 ...

  5. IE6支持兼容max-height、min-height CSS样式

    1.IE6支持max-height解决方法   -   TOP IE6支持最大高度解决CSS代码: .yangshi{max-height:1000px;_height:expression((doc ...

  6. LightOJ 1282 Leading and Trailing (数学)

    题意:求 n^k 的前三位和后三位. 析:后三位,很简单就是快速幂,然后取模1000,注意要补0不全的话,对于前三位,先取10的对数,然后整数部分就是10000....,不用要,只要小数部分就好,然后 ...

  7. Unity5.5.2 CD旋转 顺时针逆时针

    UGUI 下  Sprite_CD  在Inspector下  Image(Script) 下  Clock wise  勾选  决定  CD是顺时针还是逆时针  默认是顺时针  勾选则为逆时针

  8. C# 高斯消元项目运用

    C# 高斯消元项目运用 最近项目涉及到一个需求,需要把指定数量的多个商品,混合装入到多个不同型号的箱子中(每种型号的箱子装入商品的种类和个数是固定的).这就涉及到解多元一次方程 针对多元一次方程一般用 ...

  9. 父级(display:none)隐藏时,子节点的高度获取。

    当父节点display:none的时候,子节点的高度是0获取不到. 解决办法:用visibility替换display就可以了.

  10. 「HAOI2016」放棋子

    题目链接 戳这 前置知识 错位排序 Solution 我们可以观察发现,每一行的障碍位置对答案并没有影响. 于是我们可以将此时的矩阵化成如下形式: \[ 1\ \ 0\ \ 0\ \ 0\\ 0\ \ ...