P1935 [国家集训队] 圈地计划
先看一道较为类似的题:文理分科。
在那道题里,我们的最小割模型中有以下几种边:
-
,边权为其中,
表示在第 行第 列的人。这条边保留表示在这个人选文科;割掉则是选理科。 -
,边权为 。这条边保留表示当前这个人选理科;反之选文科。
-
对于一个人及其上下左右的组合
,我们建立虚点-
,边权为 ;以及 ,边权为 (满足 )。 -
,边权为 ;以及 ,边权为 (满足 )。
-
回归这道题。我们不妨把那个
但是还有个不同点:这题要求两个位置不一样才有贡献——考虑对棋盘黑白染色,对于黑点,我们还是按照
#include <bits/stdc++.h>
#define FL(i, a, b) for(int i = (a); i <= (b); i++)
#define FR(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
typedef long long ll;
const int S = 110, N = 100010, M = 260010;
const int f[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
const ll INF = 1e18;
struct E{int v; ll w, nxt;} e[M << 1];
int n, m, s, t, tot, tote; ll ans;
int a[S][S], b[S][S], head[N], now[N], dep[N];
void init(){
tote = 0;
memset(head, -1, sizeof(head));
}
void Adde(int u, int v, ll w){
e[tote] = {v, w, head[u]}, head[u] = tote++;
}
void Add(int u, int v, ll w){
Adde(u, v, w), Adde(v, u, 0);
}
int id(int x, int y){
return (x - 1) * m + y;
}
int bfs(){
queue<int> q; q.push(s);
memset(dep, 0, sizeof(dep)), dep[s] = 1;
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = now[u] = head[u]; ~i; i = e[i].nxt)
if(e[i].w && !dep[e[i].v])
q.push(e[i].v), dep[e[i].v] = dep[u] + 1;
}
return dep[t];
}
ll dfs(int u, ll in){
if(u == t) return in; ll out = 0;
for(int i = now[u]; ~i && in; i = e[i].nxt){
int v = e[i].v; ll w = e[i].w; now[u] = i;
if(dep[v] == dep[u] + 1 && w){
ll flow = dfs(v, min(in, (ll)w));
in -= flow, out += flow;
e[i].w -= flow, e[i ^ 1].w += flow;
}
}
if(!out) dep[u] = 0; return out;
}
ll dinic(){
ll ret = 0;
while(bfs()) ret += dfs(s, INF);
return ret;
}
int main(){
scanf("%d%d", &n, &m);
init(), s = 0, t = ++(tot = n * m);
FL(i, 1, n) FL(j, 1, m){
scanf("%d", &a[i][j]), ans += a[i][j];
if((i + j) & 1) Add(s, id(i, j), a[i][j]);
else Add(id(i, j), t, a[i][j]);
}
FL(i, 1, n) FL(j, 1, m){
scanf("%d", &b[i][j]), ans += b[i][j];
if((i + j) & 1) Add(id(i, j), t, b[i][j]);
else Add(s, id(i, j), b[i][j]);
}
FL(i, 1, n) FL(j, 1, m){
int val; scanf("%d", &val);
FL(k, 0, 3){
int x = i + f[k][0], y = j + f[k][1];
if(x < 1 || x > n || y < 1 || y > m) continue;
ans += val, Add(s, ++tot, val);
Add(tot, id(i, j), INF), Add(tot, id(x, y), INF);
ans += val, Add(++tot, t, val);
Add(id(i, j), tot, INF), Add(id(x, y), tot, INF);
}
}
printf("%lld\n", ans - dinic());
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现