发现自己一个图都不会建。(好菜啊 )
我们可以发现,这道题的k种物品是互不关联的。那我们就一个一个物品跑。记得最后检验一下自己跑出的总流是否等于顾客要的sum值,若非就输出-1。
上马!
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<cstdlib>
#define Pair pair <int, int>
using namespace std;
const int N = 5002, M = 900002, lim = 0x3f3f3f3f;
int sell[N][52], buy[N][52], k, f, prep[N], pree[N], dis[N], s, t, n, m, cnt, val[M], flow[M], to[M], head[N], nxt[M], h[N];
inline int read() {
int x = 0, f = 1;
char s = getchar();
while(! isdigit(s)) {
if(s == '-')
f = -1;
s = getchar();
}
while(isdigit(s)) {
x = (x << 1) + (x << 3) + (s ^ 48);
s = getchar();
}
return x * f;
}
inline void print(int x) {
if(x < 0) {
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
inline int Min(const int x, const int y) {
if(x < y)
return x;
return y;
}
inline void addEdge(const int u, const int v, const int w, const int Val) {
to[++ cnt] = v;
nxt[cnt] = head[u];
flow[cnt] = w;
val[cnt] = Val;
head[u] = cnt;
to[++ cnt] = u;
nxt[cnt] = head[v];
flow[cnt] = 0;
val[cnt] = -Val;
head[v] = cnt;
}
Pair EK() {
int res = 0, maxflow, ans = 0;
memset(h, 0, sizeof h);
while(f) {
priority_queue <Pair, vector <Pair>, greater <Pair> > q;
for(int i = 1; i <= t; ++ i)
dis[i] = -1;
dis[s] = 0;
q.push(Pair(0, s));
while(! q.empty()) {
Pair now = q.top();
q.pop();
int u = now.second;
if(dis[u] < now.first)
continue;
for(int i = head[u]; ~i; i = nxt[i]) {
int v = to[i];
if(flow[i] > 0 && (dis[v] < 0 || dis[v] > dis[u] + val[i] + h[u] - h[v])) {
dis[v] = dis[u] + val[i] + h[u] - h[v];
prep[v] = u;
pree[v] = i;
q.push(Pair(dis[v], v));
}
}
}
if(dis[t] < 0)
break;
maxflow = f;
for(int i = 1; i <= t; ++ i)
h[i] += (dis[i] == -1 ? 0 : dis[i]);
for(int i = t; i != s; i = prep[i])
maxflow = Min(maxflow, flow[pree[i]]);
if(maxflow == lim)
exit(0);
res += maxflow * h[t];
ans += maxflow;
f -= maxflow;
for(int i = t; i != s; i = prep[i]) {
if(flow[pree[i]] != lim)
flow[pree[i]] -= maxflow;
if(flow[pree[i] ^ 1] != lim)
flow[pree[i] ^ 1] += maxflow;
}
}
return Pair(res, ans);
}
int main() {
int x, sumflow, ans, sum;
Pair ret;
while(scanf("%d", &n), n) {
m = read();
k = read();
s = n + m + 1;
t = s + 1;
ans = sumflow = sum = 0;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= k; ++ j) {
buy[i][j] = read();
sum += buy[i][j];
}
for(int i = 1; i <= m; ++ i)
for(int j = 1; j <= k; ++ j)
sell[i][j] = read();
for(int p = 1; p <= k; ++ p) {
memset(head, -1, sizeof(int) * (n + m + 3));
cnt = -1;
f = lim;
for(int i = 1; i <= n; ++ i)
addEdge(s, i, buy[i][p], 0);
for(int i = 1; i <= m; ++ i)
addEdge(i + n, t, sell[i][p], 0);
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j) {
x = read();
addEdge(i, j + n, sell[j][p], x);
}
ret = EK();
sumflow += ret.second;
ans += ret.first;
}
if(sumflow == sum)
print(ans);
else
print(-1);
putchar('\n');
}
return 0;
}