首页 > 代码库 > bzoj 2127: happiness
bzoj 2127: happiness
Description
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每 个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理 科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
Input
第 一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。
Output
输出一个整数,表示喜悦值总和的最大值
Sample Input
1 1
100 110
1
1000
Sample Output
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数
HINT
Source
为了博多的加强版。。。
首先这种划分成两个集合,然后满足一些条件会有收益求最优分配方案的题目
一般考虑总收益减去最小割,
理解起来就是本来这些收益全部可以获取,但要分为两个集合的话就是必须要舍弃一些边使得S,T不连通(分成两个集合),要舍弃的最少,就是最小割;
为了博多比较简单,只要在同一个集合中收益是相同的,但这个题略有不同;
具体的话2016年论文说得很好。。。
// 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; const double eps=1e-5; 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],to[N],nxt[N],level[N],S,T,q[N*10],cnt=1,n,m,tt; double s[N],F; int id[200][200],a[200][200],b[200][200],v1[200][200],v2[200][200],v3[200][200],v4[200][200]; int valt; inline void Addedge(RG int x,RG int y,RG double z) { to[++cnt]=y,s[cnt]=z,nxt[cnt]=head[x],head[x]=cnt; } inline void lnk(RG int x,RG int y,RG double 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]-0>=eps&&level[y]==0){ level[y]=level[x]+1; q[sum++]=y; } } } return 0; } inline double dfs(RG int x,double maxf){ if(x==T) return maxf; double ret=0; for(RG int i=head[x];i;i=nxt[i]){ int y=to[i];double f=s[i]; if(level[y]==level[x]+1&&f-0>=eps){ double 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();S=0,T=n*m+1; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m;j++) id[i][j]=++tt; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m;j++) a[i][j]=gi(),lnk(S,id[i][j],a[i][j]),valt+=a[i][j]; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m;j++) b[i][j]=gi(),lnk(id[i][j],T,b[i][j]),valt+=b[i][j]; for(int i=1;i<=n-1;i++) for(RG int j=1;j<=m;j++) v1[i][j]=gi(),valt+=v1[i][j]; for(RG int i=1;i<=n-1;i++) for(RG int j=1;j<=m;j++) v2[i][j]=gi(),valt+=v2[i][j]; for(RG int i=1;i<=n-1;i++) for(RG int j=1;j<=m;j++){ lnk(S,id[i][j],v1[i][j]/2.0);lnk(S,id[i+1][j],v1[i][j]/2.0); lnk(id[i][j],T,v2[i][j]/2.0);lnk(id[i+1][j],T,v2[i][j]/2.0); lnk(id[i][j],id[i+1][j],(v1[i][j]+v2[i][j])/2.0); lnk(id[i+1][j],id[i][j],(v1[i][j]+v2[i][j])/2.0); } for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m-1;j++) v3[i][j]=gi(),valt+=v3[i][j]; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m-1;j++) v4[i][j]=gi(),valt+=v4[i][j]; for(RG int i=1;i<=n;i++) for(RG int j=1;j<=m-1;j++){ lnk(S,id[i][j],v3[i][j]/2.0);lnk(S,id[i][j+1],v3[i][j]/2.0); lnk(id[i][j],T,v4[i][j]/2.0);lnk(id[i][j+1],T,v4[i][j]/2.0); lnk(id[i][j],id[i][j+1],(v3[i][j]+v4[i][j])/2.0); lnk(id[i][j+1],id[i][j],(v3[i][j]+v4[i][j])/2.0); } Dinic();printf("%d\n",valt-(int)F); return 0; }
bzoj 2127: happiness