bzoj1001

来源:互联网 发布:搜索图片的软件 编辑:程序博客网 时间:2024/05/19 17:49

这题是一个裸的网络流,写的时候注意不要建错图哦~

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define N 1100000using 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;}