「学习笔记」强联通分量
一.强连通分量的相关概念#
二.强联通分量的作用#
在解决图论问题时,我们可以利用强联通分量的知识,将图中的各个强连通分量都缩成一个点,便于解决问题。有时,通过求强连通分量,可以得出图中环及环的长度。
三. 算法求强联通分量#
基本思路#
先考虑一下强连通分量的性质:存在一条路径可以从任意一点出发再到达该点。
在查找过程中,可以对经过的点标记。发现节点 连向的节点 被标记过,那么就说明找到了一条路径,这条路径上的所有节点构成一个强联通分量。为了保存这条路径上的节点,最合适的数据结构就是栈。找到路径时,逐个弹出栈中的元素,直到起始节点。再继续搜索其它强连通分量。
算法讲解#
需要对每一个节点 创建以下两个变量:
表示 时节点 被搜索到的次序。
表示节点 能够回溯到的最早的在栈中的节点。用定义来解释:设以节点 为根的子树为 ,那么 。
然后我们就能轻易得出三个性质:
-
以 为根节点的子树中的任意一个节点的 值都小于 。
-
从根出发的一条路径上的 值严格递增。
-
从根出发的一条路径上的 值严格非降。
接下来 图中的所有节点。
搜索过程中,对于相邻的节点 和 ,考虑以下三种情况:
-
节点 未被访问过:继续对节点 进行 。回溯过程,用 更新 。因为存在节点 到 的直接路径,那么节点 能回溯到栈中的节点,节点 必然也能回溯到。
-
节点 被访问过,已经在栈中:用 来更新 。
-
节点 被访问过,但不在栈中:说明 被搜索完毕,其所在的强联通分量已经被处理,所以不用被其进行操作。
对于一个强连通分量图,容易得到,在该图中只有一个节点 满足 ,且该点一定是在 过程中被访问的第一个节点。因为它的 和 值最小,不会被该强连通分量中的其他节点所影响。
因此,在回溯的过程中只需要判断 是否成立,如果成立,那么节点 以及上方的节点构成一个强连通分量。
代码实现#
stack<int> sta;
vector<int> SCC[N];//记录强连通分量中的点。
int tim = 0, head[N], dfn[N], low[N], col[N], cnt = 0;
//tim:时间戳。
//col_i:表示第i个点属于的强联通分量编号。
void tarjan (int u) {
dfn[u] = low[u] = ++ tim;//初始该点的dfn=low=时间戳。
sta.push (u);//当前节点进栈。
insta[u] = true;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
tarjan (v);
low[u] = min (low[u], low[v]);
//没有被搜索过,用 low_v 值更新 low_u 值。
}
else if (insta[v]) {
low[u] = min (low[u], dfn[v]);
//搜索过的节点在栈中,用 dfn_v 值更新 low_u 值。
}
}
if (dfn[u] == low[u]) {//找到一个 SCC。
cnt ++;//编号+1。
int v;
while (u != v) {
v = sta.top ();//不断取栈顶。
sta.pop ();//出栈。
insta[v] = false;//不在栈中。
col[v] = cnt;//v点属于第cnt个SCC中。
SCC[cnt].push_back (v);//将v点加入第cnt个SCC中。
}
}
}
易证,时间复杂度为 。
四.例题讲解#
P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G#
将爱慕关系建为一个有向图,那么在同一个强连通分量中的牛都互相爱慕。
那我们可以将强连通分量看做一个点,缩点后的奶牛就不会出现互相爱慕的情况了。
由题面可知,只有不爱慕其它奶牛才能当明星,那么我们就要在缩点后的图找出度为 的点。
然后得到两个结论:
缩点后,如果只有一个点出度为 ,则明星的数量为这个点的强连通分量的大小。
缩点后,如果有多个点出度为 ,那么没有明星。
这样就解决了。
P2272 [ZJOI2007]最大半连通子图#
用 算法缩点后去重边,题目就变成了求最长链以及最长链个数。
缩点后的图是一个 ,拓扑排序跑 转移即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!