進階圖論

by FHVirus

今天要學什麼?

  • DFS Tree
  • 關節點
  • SCC
  • BCC
  • BCC

對沒錯!BCC 有兩種!

References

小約定們

沒有特別註明時,

「圖」都是指「無向簡單連通圖」;

點數記為 \(N\),邊數記為 \(M\),

\(N, M \leq 10^5\),

且點編號為 1-base。

講師習慣的命名方式。

const int N = 1e5 + 225;
int n;
// The Graph (Adjacency List)
vector<int> adj[N];
// Visited Tag
bool vis[N];

DFST

DFS Tree (x)

Don't FST (o)

把所有點

按照 DFS 序編號

0

1

2

3

4

5

6

7

8

9

從這個點開始,

就把他當根

Tree Edge

Back Edge

性質一

對於每一個節點,

其在 DFST 上的祖先

編號一定小於自己。

性質二

無向圖的 DFST 上不存在 Cross Edge。

直觀(不嚴謹)證明:

若存在 Cross Edge,

則在 DFS 時會被走過去,

此邊會變成 Tree Edge。

實作應該很簡單吧!

const int N = 1e5 + 225;
int n;
vector<int> adj[N];
// Number vertex by pre-order traverse
// owo is the timestamp, 1-based
int pre[N], ++owo;
void dfs(int u){
	pre[u] = ++owo;
    for(int v: adj[u]){
    	// Not having a pre[] value
        // is the same as not visited
    	if(!pre[v]) dfs(v);
    }
}

把 DF Tree 上的點編號好即可!

這要做啥?

等等就知道!

Articulation Vertex

關節點

關節點 [名詞]

即「割點 Cut Vertex」,

拔掉之後會使一張圖不聯通的點。

誰是關節點?

答對了嗎?

怎麼找?

對於一個節點 u,若 u 在 DFST 中:

  • 是根節點且有多個子樹

  • 非根節點且至少有一子樹沒有 Back Edge 到 u 的祖先

則 u 是關節點。

實作上,我們要對每個節點 \(u\) 紀錄「\(u\) 的子節點最高可以

怎麼做?

一邊建 DFST 一邊做事!

投票:需要示範嗎?

Bridge / Cut Edge

橋 [名詞]

拔掉之後會使一張圖不聯通的邊。

誰是橋?

答對了嗎?

怎麼找?

在 DFST 中,

對於一個節點 u 與其一子節點 v ,

若 v 的子樹中

不存在 Back Edge 到 u 或 u 的祖先,

則邊 \((u, v)\) 是橋。

小心重邊!

怎麼做?

也是一邊建 DFST 一邊做事!

投票:需要示範嗎?

Strongly Connected Component

強聯通分量

以下討論的是有向圖喔!

若一張有向圖中的一個分量滿足:

「對於此分量的每的點對 \((u, v)\),

都存在 \(u \rightarrow v\) \(v \rightarrow u\) 的路徑」

則此分量為連通分量。

相對的,

若一張有向圖中的一個分量滿足:

「對於此分量的每的點對 \((u, v)\),

都存在 \(u \rightarrow v\)  \(v \rightarrow u\) 的路徑」

則此分量為連通分量。

這裡先不討論弱連通分量。

這張圖有哪些 SCC 呢?

把 SCC 縮起來的話呢?

變成一張 DAG(沒有環)!

為什麼會是 DAG?

直觀(不嚴謹)證明:

如果縮點之後有環,

則環上的 SCC 一定會被縮在一起!

怎麼做?

Alg[0] : Kosaraju's

翻過去又翻回來再翻過去

作法:

  • 先 DFS 一次,紀錄「離開點」的順序
  • 將所有邊顛倒,依照離開節點的順序之逆序走訪每一個點,遇到沒有被走訪過的點時,將其加入現在的 SCC 中
  • 再對原圖做縮點

實作!

投票:需要示範嗎?

不過讀書會都快一學期了應該要可以自己做出來吧?

可以看看裡面的例題喔!

Alg[1] : Tarjan

這傢伙會一直出現

作法:跟找橋、關節點很像!

  • 一邊建 DFST 一邊紀錄「自己及子樹中能透過一條 Back Edge 到達的最高祖先」,即 low 值。
  • 若一個點的 low 值為他自己,則將子樹中還不屬於任何 SCC 的人加入自己的 SCC!

0

1

2

3

4

5

6

7

8

9

0

0

2

0

0

5

5

5

8

9

low 值

實作!

投票:需要示範嗎?

注意:演算法筆記裡的做法不太一樣

(跟他線上討論過了,有興趣去看下方連結)

給定一張有向圖,求最少需要從幾個點開始 DFS 才能經過所有點至少一次。

 

(跟前面 tmw 面試題一模一樣)

給有向圖 \(G\)(可能有自環或重邊),

並建構一張新的圖 \(T(G)\),頂點集跟原圖 \(G\) 一樣。

在 \(T(G)\)存在一條有向邊 \(u \rightarrow v\) 若且唯若在 \(G\) 中存在一條 \(u\) 到 \(v\) 的路徑。

我們定義有向圖中的集團是一個點集合\(U\),

對任何集合內的兩個點 \(u, v\),

必定存在一條 \(u \rightarrow v\) \(v \rightarrow u\) 的有向邊。

集團的大小定義為這個集團的頂點個數。

現在給你一張圖\(G\),請求出 \(T(G)\)的最大集團大小。

題目等價於求最大弱連通分量。

給定一個長度為 \(n \leq 3 \cdot 10^5\) 的整數序列,

有一個人要從任一位置 \(i\) 出發,

且可以動到 \(i \pm 1\) 的條件是 \(a_i \geq a_{i \pm 1}\)。

又另外在一些位置設置噴射裝置,

使到達此位置的人可以移動到任一位置。

求最多可以經過多少個位置?

給定一張 \(n \leq 10^6\) 個點的圖,求最大弱聯通分量。

Bridge Connected Component

邊雙連通分量

邊雙連通分量 [名詞]

不存在橋的連通分量。

怎麼做?

縮點不走橋。

好好判重邊!

縮完點之後變成一棵樹!

沒有環!

BiConnected Component

點雙聯通分量

點雙連通分量 [名詞]

不存在關節點的連通分量。

Subtitle

Subtitle

Subtitle

Subtitle

Made with Slides.com