[复习] 图连通性
搜索生成树
定义(无向边方向是边第一次被遍历时所指的方向)
- 树边,搜索到一个新的点连的边,构成生成树。
- 返祖边,搜索到一个指向当前点到根的路径上的一个点的边。
- 前向边,指向生成树子树内一个点的边。
- 横叉边,其他边,指向兄弟子树。
有向图dfs生成树 以上四种边都有。
无向图dfs生成树 只有树边和返祖边。
无向图bfs生成树 只有树边和横叉边。
Tarjan 算法
SCC 强连通分量
在有向图中,两个点强连通当且仅当两点互相可达。
强连通分量是极大的满足每个点两两强联通的子图。
注意到在 \(dfs\) 树上,一个环只有可能由树边和返祖边构成。
定义 \(dfn\) 表示 \(dfs\) 序,\(low\) 表示经过树边和返祖边能到达的最小的 \(dfn\)。
如果一个点的 \(dfn=low\) 那么它就是这个 SCC 中深度最小的点。
我们到达一个新的点,将它加入栈,之后只用栈中的 \(dfn\) 更新 \(low\)。
同时当我们找到一个 \(dfn_x=low_x\) 时,此时栈中在 \(x\) 以上的点都和 \(x\) 在用一个 SCC 中。
vector<int> g[N];
int dfn[N],low[N],dfn1;
int stk[N],bz[N],top; // bz:是否在栈中
int scc[N],sc; // 所在 SCC 的标号
void dfs(int x){dfn[x]=low[x]=++dfn1,stk[++top]=x,bz[x]=1;for(int v:g[x]) if(!dfn[v])dfs(v),low[x]=min(low[x],low[v]);else if(bz[v])low[x]=min(low[x],dfn[v]);if(dfn[x]==low[x]){++sc;while(bz[x])scc[stk[top]]=sc,bz[stk[top--]]=0;}
}
SCC 标号与拓扑序
SCC 的标号是 SCC 缩点后形成的 DAG 的拓扑序的逆序。
边双连通分量
无向图。
分量内,删除任意一条边后,任意两个点可达。
连接分量的边叫做桥,或割边。
点的边双连通性具有传递性。
在无向图中,\(dfn\) 表示 \(dfs\) 序,\(low\) 表示不经过父边能到达的最小 \(dfn\)。
因此我们需要在 \(dfs\) 中记录父亲的
如果树边 \((x,v)\) 满足 \(low_v>dfn_x\) 则这条边是桥。
点双连通分量
删掉一个点后,分量内任意点两点可达。
一个点可能属于多个点双,此时这个点是割点。
点的点双连通性不具有传递性,因为一个点可能属于多个点双。
但一条边一定只属于一个点双。
如果树边 \((x,v)\) 满足 \(low_v\ge dfn_x\) 那么 \(x\) 是割点,并且对于同一个 \(x\) 有不同的 \(v\) 满足这个条件,那么每个 \(v\) 都属于不同的点双。