Tarjan强联通分量学习笔记
1.什么是强连通分量
1.定义
给定一个有向图\(\small G=(V,E)\),若存在\(\small H\subseteq G\),\(\small H\)是连通子图,且不存在\(\small H\subsetneq F\subseteq G\),且\(\small F\)是连通子图,则称\(\small H\)为\(\small G\)的一个强连通分量。
2.说人话
满足两两互达的最大的有向图\(\small G\)的子图。
2.如何求强连通分量
1.前置芝士
时间戳:对有向图\(\small G\)的节点\(r\)进行深度优先搜索,按照每一个点第一次被访问的时间顺序,依次对有向图中的节点进行整数标记,该标记被称为时间戳,记作\(\small dfn[x]\)。
设当前节点为\(x\),下一个将要访问的节点为\(\small y\),
对于有向边\(\small (x,y)\),有以下四种情况:
1.树枝边:\(y\)是第一次被访问,即\(\small x\)是\(\small y\)的父亲节点。
2.前向边:\(y\)不是第一次被访问,且存在另一条从\(\small x\)到\(\small y\)的路径[1],即\(\small x\)是\(\small y\)的祖先节点。
3.后向边:\(y\)不是第一次被访问,且存在另一条从\(\small y\)到\(\small x\)的路径,即\(\small y\)是\(\small x\)的祖先节点。
4.横叉边:\(y\)不是第一次被访问,除此之外没有其他限制的边。
由这些边构成的集合被称为搜索树。
注意:搜索树就是原图,只不过在Tarjan算法中,为了计算强连通分量而人为对这些边进行了分类。(当时的我为此理解了一个月)
2.分析
显然,根据对\(\small dfn\)的定义,
在树枝边和前向边中,\(\small dfn[x]<dfn[y]\)
在后向边和横叉边中,\(\small dfn[x]>dfn[y]\)
上图
.png)
四种边分别用其对应种类的首字进行了标注,
节点的序号即是其对应的\(\small dfn\)。
-
对于后向边\(\small (10,8)\),因为它的存在,节点\(8,9,10\)构成了一个强连通分量。
同时对于后向边\(\small (4,2)\),节点\(2,3,4\)也构成了一个连通子图,
因此在计算强连通分量时,这种边是需要考虑的。 -
对于前向边\(\small (1,6)\),因为树枝边\(\small(1,2),(2,6)\)的存在,已经存在一条从节点\(\small1\)到节点\(\small6\)的路径,
同时它对构成强连通分量没有任何贡献(不能像后向边一样让节点\(\small 1,2,6\)构成强连通分量),
因此,在计算强连通分量时,我们忽略这种边。 -
对于横叉边\(\small (7,4),(7,5)\),我们需要讨论:
因为存在一条路径从节点\(\small 4\)到节点\(\small 7\),因此节点\(\small 2,3,4,6,7\)构成一个强连通分量
因为不存在一条路径从节点\(\small 5\)到节点\(\small 7\),因此它不对强连通分量产生贡献。
那什么横叉边有用呢 -
对于树枝边
边太多所以就不列举了,它是上述两种边能产生贡献的基础,因此必然要考虑这种边。
3.结论
- 树枝边和后向边必须考虑;
- 横叉边视情况而定;
- 前向边没有用。
4.后置芝士
设当前节点为\(x\),下一个将要访问的节点为\(\small y\),
1. 维护一个栈,这个栈内储存了两类节点
- \(\small x\)的祖先节点,记为集合\(\small A\)
- 已经访问过,并且存在一条路径能到达\(\small x\)的祖先节点的节点,记为集合\(\small B\)
可以看出,若节点\(\small y\in A\)或者\(\small y \in B\),\(\small x,y\)之间必然构成一个环
2. 追溯值
- 定义:设\(\small subtree(x)\)为搜索树中以\(\small x\)为根的子树,\(\small x\)的追溯值为满足以下节点的最小时间戳:
(1):该点在栈中。(说明此点是或者可以到达\(\small x\)的祖先节点)
(2):存在一条从\(\small subtree(x)\)出发的有向边,以该点为终点。
将此记作\(\small low[x]\)
可以看出,追溯值\(\small low[x]\)记录的是\(\small x\)所能到达的节点中,时间戳最小且这个节点本身是祖先或者它可以到达祖先(好多资料没有讲清楚这一点) - 性质
对于节点\(\small x\),若\(\small low[x]=dfn[x]\),则在搜索树中,以节点\(\small x\)构成的子树包含一个强连通分量,\(\small x\)是搜索时遇到该强连通分量的第一个节点。
如果觉得证明繁琐可以直接略过QWQ
证明:反证法。假设\(\small y\)是搜索时遇到该强连通分量的第一个节点
\(\small \therefore dfn[x]>dfn[y]\),且\(\small y\)是\(\small x\)的祖先节点
\(\small \therefore y\)位于栈中
根据强连通分量的定义,必存在一条从\(\small x\)到\(\small y\)的路径
取另一位于栈中的节点\(\small z\),分类讨论:
(1)\(\small z\)位于强联通分量中:显然,\(\small dfn[z]>dfn[y]\)
(2)\(\small z\)不位于强联通分量中:显然,不存在一条从\(\small x\)到\(\small z\)的路径
\(\small \therefore\)根据追溯值的定义,\(\small low[x]=dfn[y]\)
\(\small \therefore dfn[x]=dfn[y]\)
这与\(\small dfn[x]>dfn[y]\)矛盾!
\(\small \therefore\)假设不成立
\(\small \therefore x\)是搜索时遇到该强连通分量的第一个节点。 \(\square\)[2]
由此,当回溯\(\small x\)时,若\(\small dfn[x]=low[x]\),则从节点\(\small x\)到栈顶构成一个强连通分量。
5.算法
经过了充分冗长的铺垫,现在可以正式介绍Tarjan算法了:
- 当节点\(\small x\)被第一次访问时,初始化\(\small low[x]=dfn[x]\),将\(\small x\)入栈
- 遍历\(\small x\)指向的节点\(\small y\)
(1)若\(\small y\)未被访问过,则说明\(\small (x,y)\)是树枝边,递归访问\(\small y\),从\(\small y\)回溯后,令\(\small low[x]=min(low[x],low[y])\)。
(2)若\(\small y\)已被访问过:若\(\small y\)在栈中,根据追溯值的定义,\(\small low[x]=min(low[x],dfn[y])\);否则说明\(\small y\)所在的强连通分量已经被计算,无需作处理。 - 回溯时判断\(\small dfn[x]=low[x]\),若是则不断弹出栈顶,直到\(\small x\)出栈。
下面的代码实现了Tarjan算法
const int MAXN=1e4+3;
int num,dfn[MAXN],low[MAXN],ins[MAXN];//ins表示当前节点是否在栈中,num记录时间戳
int val[MAXN],new_val[MAXN];
vector<int> graph[MAXN];
stack<int> s;
int n,m;//n为点数,m为边数
void tarjan(int u){
low[u]=dfn[u]=++num;
ins[u]=1;
s.push(u);
for(int i=0;i<graph[u].size();i++){
int v=graph[u][i];
if(!dfn[v]){//若v未被访问,则v不会被打上时间戳
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]){
int y;
do{
y=s.top();
s.pop();
ins[y]=0;
}while(u!=y);//用do while 可以保证当栈顶即为u时也能执行
}
}
时间复杂度\(\small O(n+m)\)
3.强连通分量有什么用
缩点,这是它最基础也最广泛的用途,可以将每一个强连通分量缩成一个点,这样剩下的图就形成了一个DAG,可以进行拓扑排序等其他操作,还可优化时间复杂度
4.题目
P3387 【模板】缩点
P2341 [HAOI2006]受欢迎的牛G
P2746 [USACO5.3]Network of Schools
P2272 [ZJOI2007]最大半连通子图
参考资料
OI Wiki - 图论相关概念
OI Wiki - 强连通分量
算法竞赛进阶指南:0x67 Tarjan算法与有向图连通性
本文来自博客园,作者:cmd_pig,转载请注明原文链接:https://www.cnblogs.com/cmd-pig/articles/16541639.html

浙公网安备 33010602011771号