【题解】文理分科
题意描述

sol :
考虑如何转化问题。假设我把所有的收益都加起来,减去最少的收益就是答案。
原问题 = 总收益 - 最小割
- 文理不能同时选
考虑对于每个点 i , s 向 i 连一条容量为 art[i] 的 有向边 , i 向 t 也连一条容量为 sci[i] 的边,这样 art[i] 和 sci[i] 必须断一条。
- 对于每个点,要考虑它和上下左右同文同理时的贡献
对于同文点,记作 i2 ,从 s 向 i2 连一条容量为 same_art[i] 的边,i2 再向包括它自己的相邻点连一条容量为 inf 的边。
对于同理点,记作 i3 ,从 i3 向 t 连一条容量为 same_sci[i] 的边,再从包括它自己的相邻边向它连一条容量为 inf 的边

 我们来证明它为什么是正确的。
显然文理边至少会断一个,而对于一个点的同文或同理不能同时存在(否则存在一条流量大于 0 的路径)。对于文理边同时断掉的情况,如果断掉的是同文,就把理边恢复;如果断掉的是同理,就把文边恢复,此时同样是割。
证明完毕。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=105*105*3;
const int M=1e6+5;
int n,m,s,t,rt,a[4][N],id[3][N],res;
int lab[N],que[N],cur[N];
int tot,head[M],nxt[M],to[M],cap[M];
int dx[5]={-1,0,1,0},dy[5]={0,1,0,-1};
void add(int u,int v,int w) {
	tot++;
	nxt[tot]=head[u],head[u]=tot,to[tot]=v,cap[tot]=w;
}
bool BFS() {
	for(int i=0;i<=rt;i++) lab[i]=0;
	lab[t]=1;
	int qhead=0,qtail=0;
	que[qtail++]=t;
	while(qhead!=qtail) {
		int u=que[qhead++];
		for(int k=head[u];k;k=nxt[k]) {
			int v=to[k];
			if(cap[k^1]==0||lab[v]>0) {
				continue;
			}
			lab[v]=lab[u]+1;
//			if(v==s) return 1;
			que[qtail++]=v;
		}
	}
	return lab[s]!=0;
}
int flow(int u,int limit) {
	if(u==t) {
		return limit;
	}
	int used=0;
	for(int k=cur[u];k;k=nxt[k]) {
		int v=to[k];
		cur[u]=k;
		if(lab[u]!=lab[v]+1||cap[k]==0) {
			continue;
		}
		int tmp=min(limit-used,cap[k]);
		int ret=flow(v,tmp);
		used+=ret;
		cap[k]-=ret;
		cap[k^1]+=ret;
		if(ret==0||cap[k]==0) {
			cur[u]=nxt[k];
		}
		if(limit==used) break;
	}
	return used;
}
int has(int i,int j) {
	return (i-1)*m+j;
}
bool outside(int x,int y) {
	if(x<1||x>n||y<1||y>m) return 1;
	return 0;
}
int dinic() {
	int tot=0;
	while(BFS()) {
		for(int i=0;i<=rt;i++) cur[i]=head[i];
		tot+=flow(s,INF);
	}
	return tot;
}
int main() {
	tot=1;
	for(int i=0;i<=rt;i++) {
	    head[i]=0;
	}
	s=rt=0;
	scanf("%d%d",&n,&m);
	for(int k=0;k<4;k++) {
		for(int i=1;i<=n*m;i++) {
			scanf("%d",&a[k][i]);
			res+=a[k][i];
		}
	}
	for(int k=0;k<3;k++) {
		for(int i=1;i<=n*m;i++) {
			id[k][i]=++rt;
		}
	}
	t=++rt;
	for(int i=1;i<=n*m;i++) {
		add(s,id[0][i],a[0][i]);
		add(id[0][i],s,0);
		add(id[0][i],t,a[1][i]);
		add(t,id[0][i],0);
	}
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			int u=id[1][has(i,j)];
			int f=has(i,j);
			add(s,u,a[2][f]);
			add(u,s,0);
			for(int k=0;k<5;k++) {
				int ti=i+dx[k],tj=j+dy[k];
				if(outside(ti,tj)) continue;
				int v=id[0][has(ti,tj)];
				add(u,v,INF);
				add(v,u,0);
			}
			u=id[2][has(i,j)];
			add(u,t,a[3][f]);
			add(t,u,0);
			for(int k=0;k<5;k++) {
				int ti=i+dx[k],tj=j+dy[k];
				if(outside(ti,tj)) continue;
				int v=id[0][has(ti,tj)];
				add(v,u,INF);
				add(u,v,0);
			}
		}
	}
	printf("%d",res-dinic());
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号