【BZOJ3894】文理分科

时间:2023-03-09 16:37:27
【BZOJ3894】文理分科

最小割劲啊

原题:

 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
 小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<=100,读入数据均<=500
恩一眼秒掉,先转化成求最小得不到的收益
s->i流量为选文收益,i->t为选理收益,额外点i'和i'',其中s->i'流量为i和周围全选文的收益,然后i'到i自己和周围共5个点连边,i''同理
酱紫的话如果想要某点i和周围全选文,就要让s->i'这条边留下来,就必须割掉i自己和周围共5个点到汇的边,酱源到i自己和周围共5个点的边和s->i'就都留下来了,就表示大家一起选文的收益
注意点i的两个辅助点都要和i自己连边,因为要求i和周围四个人共五个人选的都一样,然后边数也要更大,我因为这个re了一发没1A
代码:
 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int oo=;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
const int fx[]={,-,,,},fy[]={,,,-,};
struct ddd{int nxt,y,v,rvs;}e[]; int lk[],ltp=;
inline void ist(int x,int y,int z){
e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y,e[ltp].v=z,e[ltp].rvs=ltp+;
e[++ltp].nxt=lk[y],lk[y]=ltp,e[ltp].y=x,e[ltp].v=,e[ltp].rvs=ltp-;
}
int n,m; int N; int s,t;
int lvl[];
int q[],hd=;
bool gtlvl(){
memset(lvl,,sizeof(lvl));
q[hd=]=s,lvl[s]=;
for(int k=;k<=hd;++k)
for(int i=lk[q[k]];i;i=e[i].nxt)if(e[i].v && !lvl[e[i].y])
lvl[e[i].y]=lvl[q[k]]+,q[++hd]=e[i].y;
return lvl[t];
}
int mxflw(int x,int y){
if(x==t) return y;
int bwl=,flw=;
for(int i=lk[x];i && bwl<y;i=e[i].nxt)if(e[i].v && lvl[e[i].y]==lvl[x]+)
if((flw=mxflw(e[i].y,min(y-bwl,e[i].v)))){
bwl+=flw;
e[i].v-=flw,e[e[i].rvs].v+=flw;
}
if(!bwl) lvl[x]=;
return bwl;
}
int dnc(){
int bwl=,flw=;
while(gtlvl())while(flw=mxflw(s,oo)) bwl+=flw;
return bwl;
}
inline int gtid(int x,int y){ return (x-)*m+y;}
inline bool chck(int x,int y,int z){
return x+fx[z]>= && x+fx[z]<=n && y+fy[z]>= && y+fy[z]<=m;
}
int main(){//freopen("ddd.in","r",stdin);
cin>>n>>m; N=n*m; s=,t=*N+;
int v,bwl=;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
ist(s,gtid(i,j),v=rd()),bwl+=v;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
ist(gtid(i,j),t,v=rd()),bwl+=v;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
ist(s,gtid(i,j)+N,v=rd()),bwl+=v;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
ist(gtid(i,j)+N+N,t,v=rd()),bwl+=v;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
for(int k=;k<;++k)if(chck(i,j,k)){
ist(gtid(i,j)+N,gtid(i+fx[k],j+fy[k]),oo);
ist(gtid(i+fx[k],j+fy[k]),gtid(i,j)+N+N,oo);
}
cout<<bwl-dnc()<<endl;
return ;
}