这题是一个裸的网络流,写的时候注意不要建错图哦~
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 1100000
using namespace std;
struct EDGE {
int x, y, c, next, other;
//c表示x->y的流量,other表示这条边的反向边的编号
}edge[6*N];
int head[N], h[N]; //h[i]表示从st出发,i是第几层的点
int cnt, m, n, st, ed;
inline void addEdge(int x, int y, int c) {
int k1 = ++cnt;
edge[cnt].x = x; edge[cnt].y = y; edge[cnt].c = c;
edge[cnt].next = head[x]; head[x] = cnt;
int k2 = ++cnt;
edge[cnt].x = y; edge[cnt].y = x; edge[cnt].c = c;
edge[cnt].next = head[y]; head[y] = cnt;
edge[k1].other = k2;
edge[k2].other = k1;
return ;
}
bool bfs_q() { //构建h数组
memset(h, 0, sizeof(h)); h[st] = 1;
queue<int>q;
q.push(st);
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = head[now]; i; i = edge[i].next) {
int y = edge[i].y;
if(edge[i].c > 0 && h[y] == 0) { //c>0这个条件使得多次构图成为可能
//now->y这条边还有流量,并且y没被访问过
h[y] = h[now] + 1;
q.push(y);
}
}
}
if(h[ed] > 0) return true; //最后能到ed就返回true
return false;
}
int findflow(int x, int f) {
if(x == ed) return f;
int s = 0, t;
for(int i = head[x]; i; i = edge[i].next) {
int y = edge[i].y;
if(edge[i].c > 0 && h[y] == h[x] + 1 && s < f) {
s+= (t = findflow(y, min(edge[i].c, f - s)));
edge[i].c-= t; edge[edge[i].other].c+= t;
}
}
if(s == 0) h[x] = 0;
return s;
}
int main() {
freopen("1001.in", "r", stdin);
scanf("%d%d", &n, &m);
st = 1, ed = n * m;
cnt = 0;
memset(head, 0, sizeof(head));
for(int i = 1; i <= n; ++i) {
for(int j = 1; j < m; ++j) {
int x = (i - 1) * m + j, y = (i - 1) * m + j + 1, c;
scanf("%d", &c);
addEdge(x, y, c);
}
}
for(int i = 1; i < n; ++i)
for(int j = 1; j <= m; ++j) {
int x = (i - 1) * m + j, y = i * m + j, c;
scanf("%d", &c);
addEdge(x, y, c);
}
for(int i = 1; i < n; ++i)
for(int j = 1; j < m; ++j) {
int x = (i - 1) * m + j, y = i * m + j + 1, c;
scanf("%d", &c);
addEdge(x, y, c);
}
int s = 0;
while(bfs_q())
s+= findflow(st, 999999999);
printf("%d", s);
return 0;
}