二分图
二分图
定义
给一张无向图,可以把点分成两个不相交的非空集合,并且在同一集合的点之间没有边相连,那么称这张无向图为一个二分图。
二分图的判定
一张无向图是二分图,当且仅当图中不存在奇环。
vector<vector<int>> e;
vector<int> v; // 会把所有的点染成 1 2 两种颜色
bool flag;
void dfs( int x , int color ){
v[x] = color;
for( auto y : e[x] ){
if( v[y] == 0 ) dfs( y , 3 - color );
else if( v[y] == color ){
flag = false;
return ;
}
}
}
bool check(){
flag = true;
for( int i = 1 ; flag and i <= n ; i ++ ){
if( v[i] ) continue;
dfs( i , 1 );
}
return flag;
}
二分图最大匹配
“任意两条边都没有公共端点”的边集合被称为一组的匹配。
在二分图中包含边数最多的一组匹配被称为二分图的最大匹配。
对于任意一组匹配 \(S\)(\(S\)是一个边集),属于\(S\)的边叫匹配边,匹配边的端点叫匹配点。
如果在二分图中存在连接两个非匹配点的路径\(path\),则称\(path\)是\(S\)的增广路。
增广路存在以下性质:
- 长度是奇数
- 路径上第\(1,3,5,\dots\)是非匹配边,第\(2,4,6,\dots\)是匹配边
所以对于一组匹配,把增广路上的边的状态全部取反,得到新的边集合\(S’\),则\(S'\)也是一组匹配,且匹配变数多一。
所以二分图的一组最大匹配\(S\),当且仅当二分图中不存在\(S\)的增广路。
匈牙利算法
算法流程
- 设$S=\emptyset $
- 求增广路\(path\),把路径上边的状态取反得到新的匹配\(S'\)
- 重复第2步直到没有增广路
代码实现采用深搜,从\(x\)出发寻找增广路,并且还回溯时把状态取反。
\(N\)个点\(M\)条的二分图,复杂度\(O(NM)\)
// luogu P3386
//给定一个二分图,其左侧点n个,右侧点的个数为m,边数为k,求其最大匹配的边数。
//左侧点编号[1,n],右侧点编号[1,m]。
#include <bits/stdc++.h>
using namespace std;
int n, m, k; // 左右两个集合的元素数量
vector<vector<int>> e;
vector<int> p; // 当前右侧集合对于左侧的元素
vector<bool> vis;// 右侧元素是否已经被访问过
bool match(int x) {
for (auto y: e[x]) {
if (vis[y]) continue;
vis[y] = 1;
if (p[y] == 0 or match(p[y])) { // 暂未匹配或原来匹配的左侧元素可以找到新的匹配
p[y] = x;
return true;
}
}
return false;
}
int Hungarian() {
int cnt = 0;
p = vector<int>(n + m + 1);
for (int i = 1; i <= n; i++) { // 枚举左侧元素
vis = vector<bool>(n + m + 1);
if (match(i)) cnt++;
}
return cnt;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cin >> n >> m >> k;
e = vector<vector<int>>(n + m + 1);
for (int x, y; k; k--) {
cin >> x >> y;
y += n; // 为了方便表示把右侧点映射为 [n+1,n+m]
e[x].push_back(y), e[y].push_back(x);
}
cout << Hungarian() << "\n";
return 0;
}
二分图的最小点覆盖
给一张二分图,求最小点集\(S\),使得图中任意一条边都至少有一个端点属于\(S\)。
König定理
二分图最小点覆盖包含的点数等于二分图最大匹配包含的边数。
构造方法
- 求出二分图的最大匹配
- 从左部每个非匹配点出发,再执行一次 DFS 求增广路的过程(一定会失败),标记访问过的所有点
- 取左部未被标记的点、右部被标记的点,就得到了最小点覆盖。
二分图最大独立集
给一张无向图,图的独立集就是任意两点之间没有边相连的点集,包含点数最多的独立集就是图的最大独立集。
任意两点之间都有一条边相连的子图被称作无向图的团,点数最多团就是图的最大团。
对于一般的无向图,最大团、最大独立集是 NP完全问题。
定理
无向图的最大团就是补图的最大独立集
定理
\(G\)是\(n\)个点的二分图,\(G\)的最大独立集大小等于\(n\)减去最大匹配数。
对于二分图去掉最小点覆盖,剩余的点就构成了二分图的最大独立集。