很明显是最小割。。
#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;
}
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
第一行两个正整数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列的同学同时选择理科获得的额外喜悦值。
输出一个整数,表示喜悦值总和的最大值
1 2
1 1
100 110
1
1000
1210
两人都选理,则获得100+110+1000的喜悦值。
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数