P4313
先只考虑单个人,则把 \(S\rightarrow i\) 的容量设为 \(a_i\),把 \(i\rightarrow T\) 的容量设为 \(b_i\)。
显然一个人不能同时选两类,所以他需要选一类割掉,所以是最小割。
然后我们考虑以下模型:
若 \(X\) 集合内所有点都选择了 \(A\)(把 \(B\) 的边割掉了),则能获得 \(x\) 贡献。
此时我们建一个虚点 \(u\),将 \(u\) 和 \(A\) 以一条容量为 \(x\) 的边相连,现在我们要在 \(X\) 中任意一点被割时强制要求他把这条边也割了。
我们为 \(u\) 和 \(X\) 中的所有点连上容量为 \(\infty\) 的边。由于不可能割掉 \(\infty\),只能把 \(x\) 这条边割掉。
答案即为没有被割掉的边权和。(除了 \(\infty\))
#include<bits/stdc++.h>
#define int long long
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
const int N=3e4+5;
const int MM=N*5;
const int inf=1e9;
int n,m;
int a[N][4];
int f(int x,int y){
return (x-1)*m+y;
}
bool sf(int x,int y){
if(x<1||n<x||y<1||m<y)return 0;
return 1;
}
int xx[4]={-1,0,1,0};
int yy[4]={0,1,0,-1};
struct edge{
int v,w,nxt;
}e[MM*2];
int ec=1,hd[N];
void add(int u,int v,int w){
e[++ec]={v,w,hd[u]};
hd[u]=ec;
}
int S,T;
int dis[N],cur[N];
void bfs(int st){
rep(i,1,T){
dis[i]=0;
cur[i]=hd[i];
}
queue<int>q;
q.push(st);
dis[st]=1;
int u;
while(q.size()){
u=q.front();
q.pop();
for(int i=hd[u];i;i=e[i].nxt){
if(e[i].w&&!dis[e[i].v]){
dis[e[i].v]=dis[u]+1;
q.push(e[i].v);
}
}
}
}
int dfs(int u,int flw){
if(u==T){
return flw;
}
int res=0,tmp;
for(int &i=cur[u];i&&flw;i=e[i].nxt){
if(e[i].w&&dis[e[i].v]==dis[u]+1){
tmp=dfs(e[i].v,min(flw,e[i].w));
res+=tmp;
flw-=tmp;
e[i].w-=tmp;
e[i^1].w+=tmp;
}
}
return res;
}
int dinic(){
int res=0,tmp;
while(1){
bfs(S);
tmp=dfs(S,inf);
if(!tmp){
break;
}
res+=tmp;
}
return res;
}
signed main(){
scanf("%lld %lld",&n,&m);
int sum=0;
rep(k,0,3){
rep(i,1,n){
rep(j,1,m){
scanf("%lld",&a[f(i,j)][k]);
sum+=a[f(i,j)][k];
}
}
}
S=n*m*3+1;
T=S+1;
rep(i,1,n){
rep(j,1,m){
add(S,f(i,j),a[f(i,j)][0]);
add(f(i,j),S,0);
add(f(i,j),T,a[f(i,j)][1]);
add(T,f(i,j),0);
add(S,f(i,j)+n*m,a[f(i,j)][2]);
add(f(i,j)+n*m,S,0);
add(f(i,j)+n*m*2,T,a[f(i,j)][3]);
add(T,f(i,j)+n*m*2,0);
add(f(i,j)+n*m,f(i,j),inf);
add(f(i,j),f(i,j)+n*m,0);
add(f(i,j),f(i,j)+n*m*2,inf);
add(f(i,j)+n*m*2,f(i,j),0);
rep(p,0,3){
if(sf(i+xx[p],j+yy[p])){
add(f(i,j)+n*m,f(i+xx[p],j+yy[p]),inf);
add(f(i+xx[p],j+yy[p]),f(i,j)+n*m,0);
add(f(i+xx[p],j+yy[p]),f(i,j)+n*m*2,inf);
add(f(i,j)+n*m*2,f(i+xx[p],j+yy[p]),0);
}
}
}
}
printf("%d\n",sum-dinic());
return 0;
}

浙公网安备 33010602011771号