文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
科,则增加same_science[i]j[]的满意值。
小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。
第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];
一道很不错的最小割模型混杂题,画了好久才跑对QAQ...
// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define RG register
using namespace std;
typedef long long ll;
const int N=1000050;
const int Inf=19260817;
int gi(){
int x=0,flag=1;
char ch=getchar();
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) flag=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
return x*flag;
}
int head[N],nxt[N],to[N],s[N],cnt=1,n,m;
int a[550][550],b[550][550],c[550][550],d[550][550];
int id[550][550][3],tt,S,T,level[N],q[N*5],F,tot;
int mx[5]={1,-1,0,0},my[5]={0,0,1,-1};
inline void Addedge(RG int x,RG int y,RG int z) {
to[++cnt]=y,s[cnt]=z,nxt[cnt]=head[x],head[x]=cnt;
}
inline void lnk(RG int x,RG int y,RG int z){
Addedge(x,y,z),Addedge(y,x,0);
}
inline bool bfs(){
for(RG int i=S;i<=T;i++) level[i]=0;
q[0]=S,level[S]=1;int t=0,sum=1;
while(t<sum){
int x=q[t++];
if(x==T) return 1;
for(RG int i=head[x];i;i=nxt[i]){
int y=to[i];
if(s[i]&&level[y]==0){
level[y]=level[x]+1;
q[sum++]=y;
}
}
}
return 0;
}
inline int dfs(RG int x,int maxf){
if(x==T) return maxf;
int ret=0;
for(RG int i=head[x];i;i=nxt[i]){
int y=to[i],f=s[i];
if(level[y]==level[x]+1&&f){
int minn=min(f,maxf-ret);
f=dfs(y,minn);
s[i]-=f,s[i^1]+=f,ret+=f;
if(ret==maxf) break;
}
}
if(!ret) level[x]=0;
return ret;
}
inline void Dinic(){
while(bfs()) F+=dfs(S,Inf);
}
int main(){
n=gi(),m=gi();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
a[i][j]=gi(),tot+=a[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
b[i][j]=gi();tot+=b[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
c[i][j]=gi();tot+=c[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
d[i][j]=gi();tot+=d[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<3;k++){
id[i][j][k]=++tt;
}
S=0,T=tt+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
lnk(S,id[i][j][0],a[i][j]);
lnk(id[i][j][0],T,b[i][j]);
lnk(id[i][j][0],id[i][j][1],Inf);
lnk(id[i][j][2],id[i][j][0],Inf);
lnk(id[i][j][1],T,d[i][j]);
lnk(S,id[i][j][2],c[i][j]);
for(int k=0;k<4;k++){
int x=i+mx[k],y=j+my[k];
if(1<=x&&x<=n&&1<=y&&y<=m){
lnk(id[x][y][0],id[i][j][1],Inf);
lnk(id[i][j][2],id[x][y][0],Inf);
}
}
}
Dinic();printf("%d\n",tot-F);
return 0;
}