BZOJ 2127 Happiness 最小割

很明显是最小割。。

#include <cstdio>
#define FOR(i,j,k) for(i=j;i<=k;++i)
#define min(i,j) ((i)<(j)?(i):(j))
const int inf = 0x3f3f3f3f, N = 10005, M = 300005, K = 105;

int level[N], cnt = 1, cur[N], v[M], p[M], h[N], q[M], s = 0, t, w[M];
int a[K][K], b[K][K], down[K][K], right[K][K];
void add(int a, int b, int c, int d = 1) {
    p[++cnt] = h[a]; v[cnt] = b; w[cnt] = c; h[a] = cnt;
    p[++cnt] = h[b]; v[cnt] = a; w[cnt] = d * c; h[b] = cnt;
}

bool bfs() {
    int f = 0, r = 0, u, i;
    for (i = s; i <= t; ++i) level[i] = -1;
    q[r++] = s; level[s] = 1;
    while (f < r) {
        u = q[f++];
        for (i = h[u]; i; i = p[i]) {
            if (w[i] && level[v[i]] == -1) {
                level[v[i]] = level[u] + 1;
                q[r++] = v[i];
            }
        }
    }
    return level[t] > 0;
}

int dfs(int u, int low) {
    int i, tmp = 0, res = 0;
    if (u == t) return low;
    for (i = cur[u]; i && res < low; i = p[i]) {
        if (w[i] && level[v[i]] == level[u] + 1) {
            tmp = dfs(v[i], min(w[i], low - res));
            w[i] -= tmp; w[i ^ 1] += tmp; res += tmp;
            if (w[i]) cur[u] = i;
        }
    }
    if (!res) level[u] = -1;
    return res;
}

int dinic() {
    int ans = 0, i;
    while (bfs()) {
        for (i = s; i <= t; ++i) cur[i] = h[i];
        ans += dfs(s, inf);
    }
    return ans;
}

int main() {
    #define id(i,j) ((i-1)*m+j)
    int i, j, x, n, m, ss = 0;
    scanf("%d%d", &n, &m);
    t = n * m + 1;
    FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]), ss += a[i][j], a[i][j] *= 2;
    FOR(i,1,n) FOR(j,1,m) scanf("%d", &b[i][j]), ss += b[i][j], b[i][j] *= 2;
    FOR(i,1,n-1) FOR(j,1,m) {
        scanf("%d", &x); ss += x; a[i][j] += x; a[i + 1][j] += x;
        down[i][j] += x;
    }
    FOR(i,1,n-1) FOR(j,1,m) {
        scanf("%d", &x); ss += x; b[i][j] += x; b[i + 1][j] += x;
        down[i][j] += x;
    }
    FOR(i,1,n-1) FOR(j,1,m) add(id(i, j), id(i + 1, j), down[i][j]);
    FOR(i,1,n) FOR(j,1,m-1) {
        scanf("%d", &x); ss += x; a[i][j] += x; a[i][j + 1] += x;
        right[i][j] += x;
    }
    FOR(i,1,n) FOR(j,1,m-1) {
        scanf("%d", &x); ss += x; b[i][j] += x; b[i][j + 1] += x;
        right[i][j] += x;
    }
    FOR(i,1,n) FOR(j,1,m-1) add(id(i, j), id(i, j + 1), right[i][j]);
    FOR(i,1,n) FOR(j,1,m) {
        add(s, id(i, j), a[i][j], 0); add(id(i, j), t, b[i][j], 0);
    }
    printf("%d", ss - dinic() / 2);
    return 0;
}

2127: happiness

Description

高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

Input

第一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

Output

输出一个整数,表示喜悦值总和的最大值

Sample Input

1 2
1 1
100 110
1
1000 

Sample Output

1210

【样例说明】

两人都选理,则获得100+110+1000的喜悦值。

【数据规模】

对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

你可能感兴趣的:(最小割,网络流,最大流,OI,bzoj)