Description
有一个 M×N M × N 的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第 i i 行至少放置了 个士兵, 第j列至少放置了 Cj C j 个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。
Input
第一行两个数 M,N,K M , N , K 分别表示棋盘的行数,列数以及障碍的个数。 第二行有 M M 个数表示 。 第三行有 N N 个数表示 。 接下来有 K K 行,每行两个数 表示 (X,Y) ( X , Y ) 这个格子是障碍。
Output
输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出“JIONG!” (不含引号)
Sample Input
4 4 4
1 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
Sample Output
4
HINT
M,N≤100,0≤K≤M×N M , N ≤ 100 , 0 ≤ K ≤ M × N
Solution
azi只会做傻逼题
azi为什么傻逼题都要交这么多次啊
最大流
- 最少使用多少 ⇔ ⇔ 最多不用多少
- num1[i] n u m 1 [ i ] 表示第 i i 行有多少格子没有障碍
- 表示第 i i 列有多少格子没有障碍
- 往每一行连边,流量为 num1[i]−L[i] n u m 1 [ i ] − L [ i ]
- 每一列往 T T 连边,流量为
- 若第 i i 行第 列没有障碍,则第 i i 行往第 列连边,流量为 1 1 <script type="math/tex" id="MathJax-Element-55">1</script>
#include<bits/stdc++.h>
using namespace std;
#define N 1001
#define INF (1e9)
#define rep(i, a, b) for (int i = a; i <= b; i++)
inline int read() {
int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
struct edge { int v, c, next; }e[50001];
int head[5001], tot = 1;
int n, m, k, S, T, sum;
bool a[N][N];
int L[N], C[N], num1[N], num2[N];
int dep[N], q[N];
inline void add(int u, int v, int c) {
e[++tot] = edge{ v, c, head[u] }; head[u] = tot;
e[++tot] = edge{ u, 0, head[v] }; head[v] = tot;
}
inline bool bfs() {
int l = 1, r = 1;
memset(dep, 0, sizeof dep); q[r] = S, dep[S] = 1;
while (l <= r) {
int u = q[l++];
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].v, c = e[i].c;
if (c > 0 && !dep[v]) dep[v] = dep[u] + 1, q[++r] = v;
}
}
return (bool)dep[T];
}
int dfs(int u, int dis) {
if (u == T || dis <= 0) return dis;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].v, c = e[i].c;
if (dep[v] != dep[u] + 1 || c <= 0) continue;
int d = dfs(v, min(dis, c));
if (d > 0) { e[i].c -= d, e[i ^ 1].c += d; return d; }
}
return 0;
}
int main() {
scanf("%d%d%d", &n, &m, &k); T = n + m + 1;
rep(i, 1, n) L[i] = read(), num1[i] = m;
rep(i, 1, m) C[i] = read(), num2[i] = n;
while (k--) {
int x = read(), y = read();
a[x][y] = 1; num1[x]--, num2[y]--;
}
rep(i, 1, n) if (num1[i] >= L[i]) add(S, i, num1[i] - L[i]), sum += num1[i]; else { puts("JIONG!"); return 0; }
rep(i, 1, m) if (num2[i] >= C[i]) add(n + i, T, num2[i] - C[i]); else { puts("JIONG!"); return 0; }
rep(i, 1, n) rep(j, 1, m) if (!a[i][j]) add(i, n + j, 1);
int ans = 0; while (bfs()) ans += dfs(S, INF);
cout << sum - ans;
return 0;
}