还是建图问题,一定要仔细
网络流难点:1.问题的转化,2.图的构建
https://vjudge.net/problem/POJ-2516
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 505;
const int maxm = 105*105+2*105;
bool vis[maxn];
int pre[maxn], d[maxn], head[maxn];
int cnt;
int n, m, k;
int u, v, w, c;
int s, t;
int need[55][55];
int have[55][55];
int sum[555];
struct node
{
int s, to, next, w, c;
}e[maxm];
void init()
{
memset(head, - 1, sizeof(head));
s = 0, t = n + m + 1;
cnt = 0;
}
void addedge(int u, int v, int w, int c)//w是路径花费,c是流量
{
e[cnt].s = u;
e[cnt].to = v;
e[cnt].w = w;
e[cnt].c = c;
e[cnt].next = head[u];
head[u] = cnt ++;
e[cnt].s = v;
e[cnt].to = u;
e[cnt].w = -w;
e[cnt].c = 0;
e[cnt].next = head[v];
head[v] = cnt ++;
}
bool spfa()
{
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
memset(d, 0x3f, sizeof(d));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = 1;
while(! q.empty())
{
int h = q.front();
q.pop();
vis[h] = 0;
for(int i = head[h]; ~i; i = e[i].next)
{
if(e[i].c)
{
int v = e[i].to;
if(d[h] + e[i].w < d[v])
{
d[v] = d[h] + e[i].w;
pre[v] = i;
if(! vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
if(d[t] == inf) return 0;
else return 1;
}
int EK()
{
int cost = 0;
int tt, minc;
while(spfa())
{
tt = t;
minc = inf;
while(pre[tt] != -1)
{
minc = min(e[pre[tt]].c, minc);
tt = e[pre[tt]].s;
}
tt = t;
while(pre[tt] != -1)
{
e[pre[tt]].c -= minc;
e[pre[tt]^1].c += minc;
tt = e[pre[tt]].s;
}
cost += d[t] * minc;
}
return cost;
}
int main()
{
while(scanf("%d%d%d", &n, &m, &k) != EOF && (n + m + k))
{
bool flag = 0;
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= n ; i ++)
{
for(int j = 1; j <= k; j ++)
{
scanf("%d", &need[i][j]);
sum[j] -= need[i][j];
}
}
for(int i = 1; i <= m; i ++)
{
for(int j = 1; j <= k; j ++)
{
scanf("%d", &have[i][j]);
sum[j] += have[i][j];
}
}
int ans = 0;
for(int now = 1; now <= k; now ++)
{
init();
for(int i = 1; i <= m; i ++)
addedge(0, i, 0, have[i][now]);
for(int i = 1; i <= n; i ++)
addedge(m + i, n + m + 1, 0, need[i][now]);
int cost;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{
scanf("%d", &cost);
addedge(j, m + i, cost, min(need[i][now], have[j][now]));
}
for(int i = 1; i <= k; i ++)
{
if(sum[i] < 0)
{
flag = 1;
break;
}
}
if(flag) continue;
ans += EK();
}
if(flag) printf("-1\n");
else printf("%d\n", ans);
}
return 0;
}