Tarjan
强连通分量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32vector<int> dfn(n + 1), low(n + 1), f(n + 1);
int dfncnt = 0, flag = 0;
stack<int> st;
auto tarjan = [&](auto self, int u) -> void {
dfn[u] = low[u] = ++dfncnt;
st.push(u);
for (auto v : e[u]) {
if (!dfn[v]) {
self(self, v);
low[u] = min(low[u], low[v]);
}
else if (f[v] == 0) {
low[u] = min(low[u], low[v]);
}
}
if (dfn[u] == low[u]) {
++flag;
while (st.top() != u) {
f[st.top()] = flag;
st.pop();
}
st.pop();
f[u] = flag;
}
};
for (int i = 1; i <= n; i++) {
if (dfn[i] == 0) {
tarjan(tarjan, i);
}
}
1 | vector<int> dfn(n + 1), low(n + 1), cut(n + 1); |
只要有一个孩子回不到原来的点(也就是low[v] 》 dfn[u] , 那么这个点就是割点,注意如果是起点要额外加上有两个儿子这个条件
割边
点双连通分量
- 在一张连通的无向图中,对于两个点
和
,如果无论删去哪个点(只能删去一个)都不能使它们不连通,我们就说
和
点双连通
边双连通分量
- 在一张连通的无向图中,对于两个点
和
,如果无论删去哪条边(只能删去一个,且不能删
和
自己)都不能使它们不连通,我们就说
和
边双连通
性质:
- 边双连通具有传递性,即,若x , y
边双连通,y, z
边双连通,则
x , z 边双连通。 - 点双连通不具有传递性。
边双缩点:边双树
就像强联通分量缩点一样,我们可以把每一个边双缩成一个点来处理一些问题,然后这些点之间由原来的割边相连形成了一棵树。
最后得出一定是一棵树(森林),如果不是树,那就有环,环就是个边双。
就像强连通分量分解把一般有向图变成了有向无环图一样,我们把无向图的问题转到了树上,更好处理了,同时也保存了原来无向图的信息。
1 | vector<int> dfn(n + 1), low(n + 1), f(n + 1); |
把边缩掉之后图会变成一颗树,那么在这之上的操作性质会更好
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 梦始!
评论