poj 2226 二分图最小顶点覆盖
传送门 : http://poj.org/problem?id=2226
这个题需要的知识
1 二分图的最大匹配(网络流,或者匈牙利)
2 二分图的最小顶点覆盖等于最大匹配
左边顶点是行编号,右边顶点是列编号,每个边是一个泥坑。顶点覆盖边,就是木板覆盖泥坑。
具体看代码吧,横着扫一遍竖着再扫一遍
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1000;
char map[maxn][maxn];
vector<int>G[maxn];
void add(int x, int y) {
G[x].push_back(y);
}
int n, m;
int vis[maxn];
int match[maxn];
int id1[maxn][maxn], id2[maxn][maxn];
int dfs(int x) {
for (int i = 0; i < G[x].size(); i++){
int p = G[x][i];
if (!vis[p]) {
vis[p] = 1;
if (!match[p] || dfs(match[p])) {
match[p] = x;
return 1;
}
}
}
return 0;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%s", map[i]);
}
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (map[i][j] == '*') {
if (j == 0) id1[i][j] = ++cnt;
else {
if (id1[i][j - 1] == 0) id1[i][j] = ++cnt;
else id1[i][j] = id1[i][j - 1];
}
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (map[j][i] == '*') {
if (j == 0) id2[j][i] = ++cnt;
else {
if (id2[j - 1][i] == 0) id2[j][i] = ++cnt;
else id2[j][i] = id2[j - 1][i];
}
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (map[i][j] == '*') {
add(id1[i][j], id2[i][j]);
add(id2[i][j], id1[i][j]);
}
}
}
int ans = 0;
for (int i = 1; i <= cnt; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i)) ans++;
}
printf("%d\n", ans / 2);
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号