[複習] 圖連通性
搜尋生成樹
定義(無向邊方向是邊第一次被遍歷時所指的方向)
- 樹邊,搜尋到一個新的點連的邊,構成生成樹。
- 返祖邊,搜尋到一個指向當前點到根的路徑上的一個點的邊。
- 前向邊,指向生成樹子樹內一個點的邊。
- 橫叉邊,其他邊,指向兄弟子樹。
有向圖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\) 都屬於不同的點雙。