洛谷P1402 酒店之王 网络流
程序员文章站
2022-05-15 14:08:24
...
做一下往年省夏的题)
网络流比较显然,拆点要注意一下
一开始把超级源点S的出边容量设成inf -> wa 60分
改成1 -> wa 70分 才发现建图有问题
这样是能过样例 还能水70分 但是不合题意, 2号点也能蹭到1号点喜欢的菜了……
所以正确建图应该是源点连房间 然后房间连人 人->人拆出来的出点->菜 ->汇点 这样能保证一人一菜一房间
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Max(_A,_B) (_A>_B?_A:_B)
#define Min(_A,_B) (_A<_B?_A:_B)
#define inf 0x3f3f3f3f
int read(){
int s = 0;bool f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-') f = 0; c = getchar();}
while(c >= '0' && c <= '9') {
s = s * 10 + c - '0';
c = getchar();
}
return f == 1 ? s : -s;
}
const int maxn = 1007, maxm = 2000001;
int n, p, q;
struct edge{
int v, c, nxt;
}e[maxm << 1];
int head[maxn], eid = 0, d[maxn], Q[maxn], qh, qt, S, T;
void init() {
memset(head, -1, sizeof(head));
eid = 0;
}
void insert(int u, int v, int c) {
e[eid].v = v; e[eid].c = c; e[eid].nxt = head[u]; head[u] = eid++;
e[eid].v = u; e[eid].c = 0; e[eid].nxt = head[v]; head[v] = eid++;
}
bool bfs() {
qh = qt = 0;
memset(d, -1, sizeof(d));
d[S] = 0;
Q[qt++] = S;
while(qh != qt) {
int u = Q[qh++]; if(qh == maxn) qh = 0;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
if(e[i].c > 0 && d[v] == -1) {
d[v] = d[u] + 1;
Q[qt++] = v;
if(qt == maxn) qt = 0;
}
}
}
return d[T] != -1;
}
int dfs(int u, int flow) {
if(u == T) return flow;
int res = 0, tmp;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
if(e[i].c > 0 && d[v] == d[u] + 1) {
tmp = dfs(v,Min(flow, e[i].c));
res += tmp;
flow -= tmp;
e[i].c -= tmp;
e[i ^ 1].c += tmp;
if(flow == 0) break;
}
}
if(res == 0) d[u] = -1;
return res;
}
int dinic(){
int res = 0;
while(bfs()) res += dfs(S, inf);
return res;
}
/*
编号:点:1~2n 其中后面的n+1~2n为拆出来的中间点
p间房间:2n + 1 ~ 2n + p
q道菜: 2n + p + 1 ~ 2n + p + q
*/
int maxp, maxq;
int main() {
n = read(), p = read(), q = read();
init();
S = 0, T = maxn - 1;
maxp = 2 * n + p;
maxq = 2 * n + p + q;
for (int i = 2 * n + 1; i <= maxp; i++) insert(S, i, 1);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= p; j++) {
if(read()) {
insert(2 * n + j, i, 1);
}
}
insert(i, i + n, 1);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= q; j++) {
if(read()) {
insert(i + n, j + maxp, 1);
}
}
}
for (int i = maxp + 1; i <= maxp + q; i++) insert(i, T, 1);
printf ("%d\n", dinic());
return 0;
}