---
tags: 成大高階競技程式設計 2021
---
# 2021 Week17 - Cover & Independent set
註::bulb: 代表相對少見、較進階或與主題關聯性較低的內容,讀者可自行斟酌觀看。
---
# 點覆蓋(Vertex Cover)
```graphviz
graph {
node [label=""];
A -- B;
B -- C;
A -- C;
A -- D;
A -- E;
A, C [style=filled];
}
```
點覆蓋是圖的一個點集合,使得圖上所有邊都至少有一個端點在集合之中。
## 最小點覆蓋(Minimum Vertex Cover)
最小點覆蓋即為所有點覆蓋中點數最少的。
<hr class=dashed>
## 二分圖最小點覆蓋(Minimum Vertex Cover in bipartite graphs)
```graphviz
graph {
rankdir=LR;
subgraph cluster_X {
style=dashed;
label="X";
A, B, C, D;
}
subgraph cluster_Y {
style=dashed;
label="Y";
a, b, c, d;
}
A:ne -- b [style=bold];
B -- c [style=bold];
C:ne -- c;
C:se -- d [style=bold];
A:n -- a;
A:e -- c;
A:se -- d;
D:e -- d;
A, c, d [style=filled];
}
```
<hr class="dotted">
### Kőnig's theorem
:::danger
在任意的二分圖中,[最大匹配](https://hackmd.io/@XDEv11/NCKU-AdvCP-2021-Matching#%E6%9C%80%E5%A4%A7%E5%8C%B9%E9%85%8D%EF%BC%88Maximum-Cardinality-Matching%EF%BC%89)之邊數等於最小點覆蓋的點數
:::
> #### 證明
> > 令 $M$ 為一個最大匹配,而 $C'$ 為圖的一個點覆蓋
>
> $C'$ 的一個點最多覆蓋 $M$ 中的一條邊,所以得知 $|C'|\ge |M|$,
> 因此我們如果可以建構一個 $C$,使得 $|C|=|M|$,則 $C$ 就是最小點覆蓋。
>
> > 令 $F$ 為以 $X$ 的非匹配點為起點的 $M$-交錯路徑的邊集合,令 $Z$ 為 $F$ 的邊的端點的點集合
> >
> > > 對於一匹配邊 $e$ 的二端點 $u, v$,若 $e\in F$,則 $u, v\in Z$,若 $e\notin F$,則 $u, v\notin Z$。
> > > (前者很顯然是對的;若是 $u\in Z$,假設 $e\notin F$,那應該有一條非匹配邊 $u\in e'$ 且 $e'\in F$,但根據 $F$ 的定義,可得知 $e\in F$,與假設矛盾,因此透過反證法可確定後者之正確性)
>
> 若是讓 $C=(X\setminus Z)\cup(Y\cap Z)$,
> 對於任意一條邊 $e$,**若是 $e\in F$**,則 $e_Y\in (Y\cap Z)$;
> **若 $e\notin F$ 且 $e\in M$**,則 $e_X\notin Z$,也就是 $e_X\in(X\setminus Z)$;
> **若 $e\notin F$ 且 $e\notin M$**,因為 $e\notin M$,所以 $e_x$ 是匹配點,
> 且 $e_x$ 對應的匹配邊不在 $F$ 中(否則 $e\in F$),
> 所以 $e_X\notin Z$,$e_X\in(X\setminus Z)$;
> 因此 $C$ 是圖的一個覆蓋($|C|\ge|M|$)。
>
> $(X\setminus Z)$ 皆為匹配點,因為 $X$ 的非匹配點都屬於 $Z$,
> $(Y\cap Z)$ 也皆為匹配點,因為若是 $Z$ 中有 $Y$ 的非匹配點,則代表有 $M$-可擴增路徑,
> 且匹配邊的二端點同屬於或同不屬於 $Z$,所以一條匹配邊最多一個端點在 $C$ 之中,
> 因此 $|C|\le|M|$。
>
> 綜合上述之結論,$|C|=|M|$,$C$ 就是一個最小點覆蓋,
> 且最大匹配之邊數等於最小點覆蓋的點數。
>
> > 以上圖為例,$F=\{\overline{Dd},\ \overline{dC},\ \overline{Cc},\ \overline{cB}\}$,$Z=\{D,\ d,\ C,\ c,\ B\}$,
> > 所以 $C=\{A\}\cup\{c,\ d\}$。
因此二分圖最小點覆蓋問題,可透過[二分圖最大匹配](https://hackmd.io/@XDEv11/NCKU-AdvCP-2021-Matching#%E4%BA%8C%E5%88%86%E5%9C%96%E6%9C%80%E5%A4%A7%E5%8C%B9%E9%85%8D%EF%BC%88Maximum-Cardinality-Bipartite-Matching%EF%BC%89)求得,並且證明中也給出了一種建構方法,
可以找出一個最小點覆蓋。
```cpp!
pair<vector<int>, vector<int>> Konig(const vector<vector<int>>& adjx, const vector<int>& mx, const vector<int>& my) {
vector<int> cx{}, cy{};
queue<int> qu{}; vector<bool> vis(adjx.size());
for (int x{0}; x < adjx.size(); ++x)
if (mx[x] == -1) qu.push(x), vis[x] = true;
while (!qu.empty()) {
auto x{qu.front()}; qu.pop();
for (auto& y : adjx[x]) {
if (vis[my[y]]) continue;
qu.push(my[y]), vis[my[y]] = true;
cy.push_back(y);
}
}
for (int x{0}; x < adjx.size(); ++x)
if (!vis[x]) cx.push_back(x);
return {move(cx), move(cy)};
}
```
---
# 邊覆蓋(Edge Cover)
```graphviz
graph {
node [label=""];
A -- B [color=gray];
B -- C [style=bold];
A -- C [color=gray];
A -- D [style=bold];
A -- E [style=bold];
}
```
邊覆蓋是圖的一個邊集合,使得圖上所有點都至少連接著集合之中的一條邊。
> 如果有度數為 $0$ 的點則不存在邊覆蓋,這邊就不再討論此情況。
## 最小邊覆蓋(Minimum Edge Cover)
最小邊覆蓋即為所有邊覆蓋中邊數最少的。
:::danger
最小邊覆蓋之邊數等於點數扣掉[最大匹配](https://hackmd.io/@XDEv11/NCKU-AdvCP-2021-Matching#%E6%9C%80%E5%A4%A7%E5%8C%B9%E9%85%8D%EF%BC%88Maximum-Cardinality-Matching%EF%BC%89)之邊數
:::
> #### 證明
>
> > 令 $C'$ 為圖的一個邊覆蓋,而 $M$ 為一個最大匹配
>
> 讓每個點都對應到一條相鄰並在 $C'$ 的邊,則假設總共有 $e_2$ 條邊被 $2$ 個點對應,
> $e_1$ 條邊被 $1$ 個點對應,$e_0$ 條邊沒有被任何點對應,
> 我們知道 $e_2+e_1+e_0=|C'|$ 且 $2\times e_2+e_1=|V|$,得到 $|V|-e_2+e_0=|C'|$,
> $|V|-e_2\le|C'|$,而這 $e_2$ 條邊剛好是一個匹配,因此 $|V|-|M|\le|C'|$,
> 所以只要能夠找到一個 $C$,使得 $|C|=|V|-|M|$,$C$ 就是一個最小邊覆蓋。
>
> 透過最大匹配 $M$,對於所有的非匹配點,我們都隨便找一條與之相鄰的邊,
> 組成一個邊集合稱為 $N$,並且 $|N|=|V|-2\times |M|$,
> 讓 $C=M\cup N$,則 $|C|=|M|+|N|=|M|+|V|-2\times |M|=|V|-|M|$,
> 因此 $C$ 就是一個最小邊覆蓋,且最小邊覆蓋之邊數等於點數扣掉最大匹配之邊數。
最小邊覆蓋問題,則是可以透過[最大匹配](https://hackmd.io/@XDEv11/NCKU-AdvCP-2021-Matching#%E6%9C%80%E5%A4%A7%E5%8C%B9%E9%85%8D%EF%BC%88Maximum-Cardinality-Matching%EF%BC%89)求得,上面也給出了一種建構方法,
可以找到一個最小邊覆蓋。
---
# (點)獨立集(Indepedent (Vertex) set)
```graphviz
graph {
node [label=""];
A -- B;
B -- C;
A -- C;
A -- D;
A -- E;
B, D, E [style=filled];
}
```
獨立集是圖的一個點集合,集合中的點兩兩不相鄰。
## 最大獨立集(Maximum Independent Set)
:::danger
最大獨立集之點數等於點數扣掉最小點覆蓋之點數
:::
> #### 證明
>
> 獨立集中的點兩兩不相鄰,代表一條邊至多一個端點在集合之中,
> 所以一個集合是獨立集若且唯若其補集是點覆蓋。
>
> > 令 $I'$ 為一個獨立集,$C$ 為一個最小點覆蓋
>
> $|I'|+|I'^c|=|V|$,$|I'|+|C|\le|V|$,$|I'|\le|V| - |C|$,
> 所以如果能找到一個獨立集 $I$,使得 $|I|=|V| - |C|$,$I$ 就是一個最大獨立集。
>
> 讓 $I=C^c$,則 $|I|=|V| - |C|$,$I$ 就是一個最大獨立集,
> 且最大獨立集之點數等於點數扣掉最小點覆蓋之點數。
透過上面的證明可以知道,先找到一個最小點覆蓋,其補集就是一個最大獨立集。
---
# 邊獨立集(Indepedent Edge set)
```graphviz
graph {
node [label=""];
A -- B [color=gray];
B -- C [style=bold];
A -- C [color=gray];
A -- D [style=bold];
A -- E [color=gray];
}
```
邊獨立集是圖的一個邊集合,且集合中的邊兩兩不相鄰。
> **詳見[*匹配*](https://hackmd.io/@XDEv11/NCKU-AdvCP-2021-Matching)**
---
# Reference
* Wikipedia - [Kőnig's theorem (graph theory)](https://en.wikipedia.org/wiki/K%C5%91nig%27s_theorem_(graph_theory))
<style>
hr.thin {
height: 0.5px;
}
hr.dotted {
border-top: dotted;
height: .0em;
color: #777777;
background-color: #ffffff;
}
hr.dashed {
border-top: dashed;
height: .0em;
color: #777777;
background-color: #ffffff;
}
/* Gradient transparent - color - transparent */
hr.gradient {
border: 0;
height: 1px;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
}
/* Flaired edges, by Tomas Theunissen */
hr.flaired {
overflow: visible;
height: 30px;
border-style: solid;
border-color: black;
border-width: 1px 0 0 0;
border-radius: 20px;
background-color: #ffffff;
}
hr.flaired:before { /* Not really supposed to work, but does */
display: block;
content: "";
height: 30px;
margin-top: -31px;
border-style: solid;
border-color: black;
border-width: 0 0 1px 0;
border-radius: 20px;
}
</style>