BZOJ 3894 文理分科 最小割
对于全理/全文分别建一个点代表他 然后S->点/点->T连一条收益边 全理/全文集合里的点向它连INF的边 使得只要存在一个不是理/文 这条边就要被割掉
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef int JQK; int n, m; const int INF = INT_MAX;int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}}; int bl[105][105]; int sum = 0; int A[105][105], B[105][105], SA[105][105], SB[105][105]; int main() { int n, m; scanf("%d %d", &n, &m); dinic::MAXP = 3 * n * m + 5; int s, t; s = 3 * n * m + 1, t = s + 1; dinic::init(s, t); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &A[i][j]); sum += A[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &B[i][j]); sum += B[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &SA[i][j]); sum += SA[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &SB[i][j]); sum += SB[i][j]; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { bl[i][j] = (i + j) % 2; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int now = (i - 1) * m + j; dinic::addedge(s, now, A[i][j]); dinic::addedge(now, t, B[i][j]); dinic::addedge(s, now + n * m, SA[i][j]); dinic::addedge(now + n * m, now, INF); dinic::addedge(now + 2 * n * m, t, SB[i][j]); dinic::addedge(now, now + 2 * n * m, INF); for (int k = 0; k < 4; k++) { int dx = i + dir[k][0]; int dy = j + dir[k][1]; if (dx >= 1 && dx <= n && dy >= 1 && dy <= m) { int aim = (dx - 1) * m + dy; dinic::addedge(aim, now + 2 * m * n, INF); dinic::addedge(now + n * m, aim, INF); } } } } printf("%d\n", sum - dinic::Dinic()); return 0; }