用8w來認識圖論

建中校隊培訓

by 劉澈

OUTLINE

  • DP on tree
    • Reroot
  • DFS tree
  • Bridge Connected Components(BCC)
    • Tarjan's algorithm
    • Bridge tree
  • Biconnected Components(BCC)
    • Tarjan's algorithm
    • Block-cut tree
  • Strongly Connected Components(SCC)
    • Tarjan's algorithm & Kosaraju's algorithm 
    • Condensation graph
  • 2-SAT
  • 圖論題?

NOT COVERED

  • HLD
  • Centroid decomposition
  • Bipartite graph
  • Matching/Vertex cover/Edge cover/independent set
  • Virtual tree
  • Eulerian trail & circuit
  • Matroid

INTRO

ID: cheissmart2 cheissmart

MOTTO: 8wcp

 

 

8w

賴賴和Wiwi是一對夫妻

他們的兩個小孩: 小賴 小wi

今天考慮的圖都沒有自環

 

好題推薦: tioj 2213

樹上DP

序列是一種特別的樹

DEFINITION

題目如果是無根樹,就選隨便一個根,這個操作叫定根

定完根之後,就可以定義以每個點為根的子樹

1

2

5

3

4

1

1

6

1

7

1

8w

前綴和

序列前綴和其實是一種(退化的?)DP

還是你們都用FFT做的

前綴和對應到樹上是子樹和

int dp[N], a[N];

vector<int> G[N];

void dfs(int u, int p = -1) {
	dp[u] = a[u];
	for(int v:G[u]) if(v != p) {
		dfs(v, u);
		dp[u] += dp[v];
	}
}

一些集的定義

樹的最小支配集:點集中取出儘量少的點,使剩下的點與取出來的點都有邊相連

 

樹的最小點覆蓋:點集中取出儘量少的點,使得所有邊都與選出的點相連

 

 樹的最大獨立集:點集中取出儘量多的點,使得這些點兩兩之間沒有邊相連

可以Greedy幹嘛DP

註: 兩個做法都是 \[ O(N) \] 

加強版

樹的最小支配集

 

樹的最小點覆蓋

 

樹的最大獨立集

樹的最大權獨立集

另外兩個做法類似(left as an exercise for the reader)

Text

dp[u][0] := 考慮在 u 的子樹中,不選 u 的最大權獨立集
dp[u][1] := 考慮在 u 的子樹中,選 u 的最大權獨立集
int dp[N][2];

void dfs(int u, int p = -1) {
	dp[u][1] = w[u]; // weight of u
	for(int v:G[u]) if(v != p) {
    	dfs(v, u);
        dp[u][0] += max(dp[v][0], dp[v][1]);
        dp[u][1] += dp[v][0];
    }
}

int max_weight_indep_set() {
	dfs(1);
    return max(dp[1][0], dp[1][1]);
}

換根DP

兩種寫法:

賴賴

轉移也可以DP

CSA Tree Game

 

有一個樹,賴賴要選擇一個獨立集,Wiwi 要從剩下來的點拔掉一些點,讓任意兩個賴賴選的點都不連通

賴賴要最大化拔掉點個數,Wiwi要最小化

請問拔掉點個數

\[ N\leq10^5\]

也可以想成是DP多加一維在滾動

code

EXERCISES

POI 2016 Parade

8w所在國家是一個樹,因為舉行婚禮,所以要找一條簡單路徑讓花車走,一條道路如果洽有一個端點在路徑上,就必須封住,以擾亂社會為樂的8w想要最大化封住的道路數

\[N \leq 2\times 10^5\]

CSA Flip The Edges

8w所在國家是一個樹,他們要行婚禮,每一條街有兩種可能性(會出席婚禮 or 不會出席婚禮) ,8w每次可以選擇一條簡單路徑,然後改變(toggle)路徑上所有人的狀態,對於每條街,有三種可能性

  • 8w不希望這條街上的人來
  • 8w希望這條街上的人來
  • 8w不在意這條街上的人來不來

請問8w最少操作次數

\[N \leq 10^5\]

EXERCISE

註: 有些題目可能需要會別的(更進階的)東西

DFS Tree

Types of edges

  • Tree edge: 走到兒子的邊

  • Back edge: 走到祖先的邊

  • Forward edge: 走到非兒子的子孫的邊

  • Cross edge: 走到非直系血親的邊

1

2

5

3

4

1

1

6

1

7

1

8w

無向圖只有 tree edges 和 back edges!!

BCC(Bridge)

射人先射馬,擒賊先擒王

MOTIVATION

8w在一張連通無向圖上生活。有一天,賴賴在蛋糕上放"WIWI"字母蠟燭時,不小心放成"WWII",想到第二次世界大戰,賴賴就開始害怕: 如果有戰爭把8w家園的一條路炸毀,會不會讓家園不連通

 

請找出所有路(邊)使得如果該路被炸毀,圖就會不連通

\[ N,M \leq 10^6 \]

DEFINITION

對於一張無向連通圖,一條邊是橋(bridge) iff 把他拔掉會使圖不連通

DEFINITION

對於一張無向連通圖,如果沒有橋,則這張圖是邊雙連通(2-edge connected)

Tarjan算法的前奏

Back edge不可能是bridge!!

只要檢查 tree edge

\[ \implies \]

Tarjan的想

對於一條 tree edge 你會發現他是 bridge 的充分必要條件是:

下面那個點的子樹裡所有 back edge 的終點都在子樹裡

怎麼檢查呢?

怎麼檢查呢?

樹DP

DP什麼

low[u] := 起點在 u 的子樹中的 back edges 的終點當中, dfs 序最小值

註: dfs序改成深度也可以,但是 scc 就不能用深度但可以用dfs序,所以推薦就一律用dfs序

bool vis[N];
int tin[N], low[N], timer;
vi G[N];
void dfs(int u, int p = -1) {
    vis[u] = true;
    tin[u] = low[u] = timer++;
    for (int v : G[u]) if(v != p) {
        if (vis[v]) {
            low[u] = min(low[u], tin[v]); // 有一條從 u 開始的 back edge
        } else {
            dfs(v, u);
            low[u] = min(low[u], low[v]); // 轉移 dp
            if (low[v] == tin[v])
                IS_BRIDGE(u, v);
        }
    }
}

SOME PROPERTIES

G is a connect graph.

* 8w Property
An edge (u, v) in G is a bridge iff u, v are not connected after removing (u, v) from G.
PROOF: trivial

* 8wcp Corollary
For any simple cycle C in a graph G, each edge in C is not a bridge in G.
PROOF: trivial

* 8wcpOrz Property
If G' is a connected subgraph of G, e is a bridge in G and e is in G',
 then e is also a bridge in G'.
PROOF: trivial

記清楚名字喔,我等等會直接用

註: 其實這裡G, G' 是不是連通不重要,但是我前面只有對連通圖定義什麼是橋,事實上橋可以更廣義的定義成,拔掉會使連通塊數增加,但我懶得改了

MOTIVATION

Q: Given a connected graph G, remove as few edges  as possible so that every connected component is 2-edge connected.

 

By 8wcpOrz property, all bridges have to be removed. 

Is that enough?

 

Answer: Yes!!

PROVING TIME...

用8w, 8wcp, 和 8wcpOrz 就可以證出來了

邊雙連通分量(BCC)

因為把所有橋拔掉,剩下來每一個連通塊都是邊雙連通的,所以每一塊叫做一個邊雙連通分量

另一種定義

等價的定義: maximal 2-edge connected subgraph

假設 G 的一個子圖 G' 是邊雙連通的,顯然

  • G' 是連通的
  • G' 不包含 G 的橋

所以 G' 一定要掉在把橋拔掉後的一個連通塊裡

\[ \implies \]

註: maximal 是指 G 不存在一個子圖嚴格包含G'

Tarjan:我又回來了

怎麼找到所有 BCC 呢?

一種顯然的作法是把 bridge 拔掉然後 DFS 找連通塊

但是其實可以找橋的時候就順便做完

 

stack!!

Tarjan

int tt, bcc_cnt, vis[N], low[N], bcc[N];
vi G[N], who[N], s;
void assign(int u, int bcc_id) {
	bcc[u] = bcc_id;
    who[bcc_id].PB(u);
}
void dfs(int u, int p = -1) {
	low[u] = vis[u] = ++tt;
	s.PB(u);
	for(int v:G[u]) if(v != p) {
		if(vis[v]) low[u] = min(low[u], vis[v]);
		else {
			dfs(v, u);
			if(low[v] > vis[u]) {
				++bcc_cnt;
				int k;
				do {
                	assign(k = s.back(), bcc_cnt);
					s.pop_back();
				} while(k != v);
			}
			low[u] = min(low[u], low[v]);
		}
	}
	if(pa == -1) {
		++bcc_cnt;
		for(; s.size(); s.pop_back())
			assign(s.back(), bcc_cnt);
	}
}

Bridge Trees

一定會是樹!!

總結

對一張無向連通圖,可以用 Tarjan 算法做 BCC 分解,把每個 BCC 縮成一個點得到 bridge tree

 

\[O(N+M)\]

 

對於有些問題,於把圖的問題變成樹的問題會大大簡化問題

CF1220E Tourism

EXERCISES

BCC(Vertex)

跟邊的差不多

DEFINITION

對於一張無向連通圖,一個點是割點(articulation vertex) iff 把他拔掉會使圖不連通

DEFINITION

對於一張無向連通圖,如果沒有割點,則這張圖是點雙連通(biconnected)

Tarjan的想法

對於一個不是根點 u 你會發現他是割點的充分必要條件是:

有一個小孩子樹裡所有 back edge 的終點都在子樹裡或是u

對於根點他是割點的充分必要條件是: dfs tree 上小孩個數>=2
e.g. 賴賴跟Wiwi有兩個小孩(小賴跟小Wi)

DP什麼

low[u] := 起點在 u 的子樹中的 back edges 的終點當中, dfs 序最小值

註: dfs序改成深度也可以,但是 scc 就不能用深度但可以用dfs序,所以推薦就一律用dfs序

bool vis[N];
int tin[N], low[N], timer;
vi G[N];
void dfs(int u, int p = -1) {
    vis[u] = true;
    tin[u] = low[u] = timer++;
    int child_cnt = 0;
    for (int v : G[u]) if(v != p) {
        if (vis[v]) {
            low[u] = min(low[u], tin[v]); // 有一條從 u 開始的 back edge
        } else {
            dfs(v, u);
            if(p != -1 && low[v] >= tin[u])
            	IS_CUTPOINT(u); // u separates v from p
            child_cnt++, low[u] = min(low[u], low[v]); // 轉移 dp
        }
    }
    if(p == -1 && child_cnt > 1) IS_CUTPOINT(u);
}

SOME LEMMAS

G is a connected graph.

* 8e7 loves wiwi Lemma
If A, B are biconnected subgraphs of G and |V(A) ∩ V(B)| >= 2,
  then A U B is also a  biconnected subgraph.
PROOF. 我懶得用打的,現場講XD

* wiwi loves 8e7 Corollary
If A, B are biconnected subgraphs of G and |E(A) ∩ E(B)| >= 1,
  then A U B is also a  biconnected subgraph.
  
* 8w 1314 Observation
If (u, v) is an edge of G,
  then ({u, v}, {(u, v)}) is a biconnected subgraph of G.

* 8w forever Corollary
If e is an edge of G,
  then e belongs to at least one  biconnected subgraph of G.

SUMMARY

點雙連通分量(BCC)

Definition: A biconnected component is a maximal  biconnected subgraph

剛剛雙連通分量是把集partition

那現在也一樣嗎?

慘!!點有交集
那邊呢?

好像是 partition 耶!

PARTITION?

比較

雙連通分量是把集partition

雙連通分量是把集partition

By wiwi loves 8e7 Corollary」and 「8w forever Corollary」the set of all BCC partitions all edges.

怎麼找到所有 BCC 呢?

理論上對於每個 BCC 要把邊找出來,但實際上通常把每個 BCC 的點找出來比較有用(雖然同一個點可能在不只一個 BCC 裡)

Tarjan

int low[N], tin[N], id[N], t, cnt;
vi s, bcc[N], G[N];

void dfs(int u, int p = 0) {
	low[u] = tin[u] = ++t;
	s.PB(u);
	for(int v:G[u]) if(v != p) {
		if(tin[v]) low[u] = min(low[u], tin[v]);
		else {
			dfs(v, u);
			if(low[v] >= tin[u]) {
				cnt++;
				int k;
				do{
					k = s.back(); s.pop_back();
					bcc[k].PB(cnt);
				} while(k != v);
				bcc[u].PB(cnt);
			}
			low[u] = min(low[u], low[v]);
		}
	}
}

bool iscut[N];
vi T[N];

void build() {
	dfs(1);
	for(int i = 1; i <= n; i++) {
		if(bcc[i].size() > 1) {
			id[i] = ++cnt;
			iscut[id[i]] = true;
			for(int j:bcc[i]) {
				T[id[i]].PB(j);
				T[j].PB(id[i]);
			}
		} else {
			id[i] = bcc[i][0];
		}
	}
}

找到BCC也可以順便找割點

Claim: A vertex is an articulation vertex iff is belongs to more that 1 BCC.

證明時間!!

BLOCK-CUT-TREE

對一張無向連通圖,可以用 Tarjan 算法做 BCC 分解,得到 block-cut tree

 

\[O(N+M)\]

 

對於有些問題,於把圖的問題變成樹的問題會大大簡化問題

總結

EXERCISES

CSES 1705

EAR DECOMPOSITION

\8w教我圖論/

SCC

講了這麼多無向圖,來看看有向圖

MOTIVATION

CSES 1682

8w家庭在一張有向圖上生活,但是因為8e7都不買奶粉,所以小賴和小wi都要自己到處找食物,如果其中一個人找到食物,就會拿去找另一個人一起分享,請問是否對於任意兩個點a, b,都存在一條從 a 走道 b 的路徑

DEFINITION

A direct graph is said to be strongly connected if every vertex is reachable from every other vertex.

DEFINITION

First definition:

A strongly connected component of a directed graph G is a maximal subgraph that is strongly connected.

Second definition:
Define a relation x R y iff both vertices are reachable from the other vertex.

R is obviusly an equivalence relation.
Strongly connected components can be defined as the induced graphs of the equivalence classes.

Why are the two definitions equivalent?

CONDENSATION

By the second definition of SCC, SCC partitions the vertices.

DAG

By the first definitiom of SCC, the condensation graph must be a DAG.

There exist a path from u to v  iff there exist a path from scc(u) to scc(v) in the condensation graph.

Tarjan again

vi G[N], s;
int scc[N], d[N], low[N], cnt, tin;

void dfs(int u) {
	d[u] = low[u] = ++tin;
	s.PB(u);
	for(int v:G[u]) {
		if(!d[v]) {
			dfs(v);
			low[u] = min(low[u], low[v]);
		} else if(!scc[v]) {
			low[u] = min(low[u], d[v]);
		}
	}
	if(low[u] == d[u]) {
		cnt++;
		int t;
		do {
			t = s.back(); s.pop_back();
			scc[t] = cnt; 
		} while(t != u);
	}
}

KOSARAJU'S ALGORITHM

V<pi> G[N];
vi rG[N], order;
int scc[N], vis[N];

void dfs(int u) {
	vis[u] = 1;
	for(int v:rG[u]) if(!vis[v])
		dfs(v);
	order.PB(u);
}

void dfs2(int u, int cnt) {
	scc[u] = cnt;
	d[u] = dis;
    for(int v:G[u]) {
		if(!scc[v]) dfs2(v, cnt);
	}
}

int main() {
	int n, m;
	cin >> n >> m;
	for(int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		G[u].EB(v);
		rG[v].EB(u);
	}
	for(int i = 1; i <= n; i++) if(!vis[i])
		dfs(i);
	reverse(ALL(order));
	int cnt = 0;
	for(int i:order) if(!scc[i]) {
		dfs2(i, ++cnt);
	}
}

CORRECTNESS

如果 u --> v 而且 v --> u,顯然該演算發會把 u, v 放在同一個 SCC 裡,所以只要


如果 u -x-> v 而且 v -x-> u ,顯然該演算發不會把 u, v 放在同一個 SCC 裡

如果 u -x-> v 而且 v --> u,第二次 DFS 的 order u 一定要先 DFS 到,也就是說在圖裡(u --> v, v -x-> u) DFS 時,要先離開 v 再離開 u,不難發現,這是對的

EXERCISES

2-SAT

蛤 這是圖論喔

證明時間

EXERCISES

cses 1684 (裸)

POI2011 Conspiracy

課後問題: 想一下3-SAT怎麼做

一些(圖論)題目

小試身手一下

8w買奶粉

Puzzle game

King Game

Robot Path

Ants

水管達人

龜兔賽跑

好 spaghetti

用8w來認識圖論

By cheissmart

用8w來認識圖論

  • 2,074