二分图是什么?
二分图 是指将所有点分成两个集合, 使得所有边只出现在集合之间, 那就是二分图
二分图的性质:
- 二分图一定能进行无矛盾的染色
- 二分图一定不含有奇数环
- 二分图不一定是连通图
二分图的判定问题, 一般常用的方法是染色法判定二分图, 相邻的两个点用不同的颜色染色, 只要某个点染色不成功就说明整个图不是二分图, 染色不成功等价于相邻的点染了相同的颜色
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int e[N], ne[N], h[N], idx, color[N], n, m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool dfs(int u, int c)
{
color[u] = c; //染色
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(!color[j]) //未被染色
{
if(!dfs(j, 3 - c)) return false; //染色失败
}
else if(color[j] == c) return false; //染色失败
}
return true; //染色成功
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h); //初始化头结点
for(int i = 1; i <= m; i ++ )
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a); //建图
}
for(int i = 1; i <= n; i ++ ) //给每一个点染色
if(!color[i])
{
if(!dfs(i, 1))
{
cout << "No\n";
return 0;
}
}
cout << "Yes\n";
}
二分图的最大匹配
一些必要的概念
匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点。
最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。
增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路。
然后匈牙利算法的证明可以看这个博主, 讲的非常生动形象
总结一下: 首先每个左节点预定右节点, 看右节点是否已经匹配, 如果已经匹配了,看他匹配的对象能不能匹配别人
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int e[N], ne[N], h[N], idx, match[N], n1, n2, m;
bool st[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool find(int x)
{
for(int i = h[x]; ~i; i = ne[i])
{
int j = e[i];
if(!st[j])
{
st[j] = true; //预定
if(!match[j] || find(match[j])) // 1.是否已经匹配 2.看能不能再匹配别人
{
match[j] = x; //匹配成功
return true;
}
}
}
return false;
}
int main()
{
cin >> n1 >> n2 >> m;
memset(h, -1, sizeof h); //初始化头节点
for(int i = 1; i <= m; i ++ ) //建图
{
int a, b;
cin >> a >> b;
add(a, b);
}
int res = 0;
for(int i = 1; i <= n1; i ++ ) //每一组匹配
{
memset(st, false, sizeof st); //因为每轮预定情况不同,所以需要初始化
if(find(i)) res ++;
}
cout << res << '\n';
}
常用结论
二分图不存在奇数环
⟺
\iff
⟺ 染色法不存在矛盾(证明略)
最大匹配数 = 最小点覆盖 = 总点数 - 最大独立集 = 总点数 - 最小路径覆盖
一个匹配是最大匹配
⟺
\iff
⟺ 不存在增广路径
最小点覆盖问题:
定义: 给我们一个图, 从中选出最少的点, 使得图中的每一条边至少有一个顶点被选
在二分图中 最小点覆盖 == 最大匹配数
最大独立集问题
定义: 给我们一个图, 从中选出最多的点, 使得选出的点之间没有边
在二分图中 最大独立集 == 总点数 - 最小点覆盖 == 总点数 - 最大匹配数
最小不相交路径覆盖问题
定义: 在有向无环图中, 用最少的互不相交的路径, 将所有点覆盖
在二分图中 最小不相交路径覆盖 == n - 最大匹配数
最小路径重复点覆盖
定义: 在有向无环图中, 用最少的路径,将所有点覆盖
在二分图中, 我们先将原图做一遍传递闭包, 然后再进行二分图的最大匹配再与总点数作差就可以得到答案
最大匹配数 = 最小点覆盖 = 总点数 - 最大独立集 = 总点数 - 最小路径覆盖