二分图的最大独立集
传送门 : https://ac.nowcoder.com/acm/contest/1063/C
棋子两两冲突,放最多的棋子。
把冲突的棋子之间建条边,建好后发现选择的是最大独立集。
图中不可能有奇环,是二分图。
二分图的 最大独立集 = 顶点总数 - 最小路径覆盖 = 顶点总数 - 最大匹配
然后就amzing了呀,具体看代码就行,网络流还是匈牙利随意(网络流更快)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 220;
const int N = 200000;
int list[maxn][maxn];
int id[maxn][maxn];
int n, m;
int dis[4][2] = { {-1,-2},{-2,-1},{-2,1},{-1,2} };
vector<int>G[N];
void add(int x, int y) {
G[x].push_back(y);
}
int vis[N];
int match[N];
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;
match[x] = p;
return 1;
}
}
}
return 0;
}
int main() {
int t;
scanf("%d %d %d", &n, &m ,&t);
int x, y;
for (int i = 0; i < t; i++) {
scanf("%d%d", &x, &y);
list[x][y] = 1;
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
id[i][j] = ++cnt;
}
}
//cout << endl;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (list[i][j]) continue;
for (int k = 0; k < 4; k++) {
int x = i + dis[k][0];
int y = j + dis[k][1];
if (x >= 1 && x <= n && y >= 1 && y <= m) {
if (list[x][y]) continue;
add(id[i][j], id[x][y]);
add(id[x][y], id[i][j]);
}
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m ; j++) {
if (list[i][j]) continue;
if (!match[id[i][j]]) {
memset(vis, 0, sizeof(vis));
if (dfs(id[i][j])) ans++;
}
}
}
ans = cnt - t - ans;
printf("%d\n", ans);
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号