二分图最小点覆盖应用:
证明可得:二分图的最大匹配数 == 最小点覆盖(证明理解不能,寄了)
什么是最小点覆盖?
最小点覆盖并不只在二分图中才存在
在任意一个图中选取 最少 多少个点,可以保证 这些点 覆盖 图中所有的边
这个数量就是最小点覆盖
————————————————————————————————————————————————
Acwing:泥地
此题为思维上更巧妙的最小点覆盖应用
此题木板覆盖泥地可以重叠
思路:
-
记录每个点所在的泥地连续行、连续列(木板覆盖的是连续的区间),行对列连边 (这样的一条边上有两个点,可以理解为,要覆盖这个点(泥地)有 横着铺木板(行) 和 竖着铺木板(列) 两种方式)
-
集合自然会分为行集合、列集合,满足二分图性质;最后求的就是,最少的点覆盖所有的边(所有的泥地点),即最小点覆盖
代码:
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
#define mem(a,b) memset(a,b,sizeof a)
#define cinios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
#define sca scanf
#define pri printf
#define ul (u << 1)
#define ur (u << 1 | 1)
#define fx first
#define fy second
//#pragma GCC optimize(2)
//[博客地址](https://blog.csdn.net/weixin_51797626?t=1)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2010, M = 500010, MM = 3000010;
int INF = 0x3f3f3f3f, mod = 100003;
ll LNF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, T, S, D;
int match[N], r[N][N], c[N][N], rcnt = 1, ccnt = 1;
//记录每个点所在的泥地连续行、连续列,行对列连边,集合自然分为行集合、列集合,满足二分图性质
//最后求的就是,最少的点覆盖所有的边,即最小点覆盖
bool st[N], g[N][N];
string s[60];
//注意一下数组大小
bool find(int x) { //标准匈牙利
for (int j = 1; j <= ccnt; j++)
if (!st[j] && g[x][j]) {
st[j] = true;
int t = match[j];
if (!t || find(t)) {
match[j] = x;
return true;
}
}
return false;
}
int main() {
cinios;
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> s[i];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j && s[i][j] == '*' && s[i][j - 1] == '.')rcnt++;
//一旦遇到干净地面,泥地行编号++
if (s[i][j] == '*')r[i][j] = rcnt;//赋予该格行编号
}
rcnt++;//换行也要++
}
//对列同样操作,小心bug
for (int i = 0; i < m; i++) { //bug —— i < n, j < m
for (int j = 0; j < n; j++) {
if (j && s[j][i] == '*' && s[j - 1][i] == '.')ccnt++;
//bug —— s[j][i - 1]
if (s[j][i] == '*')c[j][i] = ccnt;//bug —— c[i][j]
}
ccnt++;
}
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (s[i][j] == '*') //对于泥地格,建边
g[r[i][j]][c[i][j]] = true;
int ans = 0;
for (int i = 1; i <= rcnt; i++) { //行集合匹配列集合
mem(st, 0);
if (find(i))ans++;
}
cout << ans;
return 0;
}
网络流(x)
抽象派(√)