高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每 个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理 科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每 个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理 科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
第 一行两个正整数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列的同学同时选择理科获得的额外喜悦值。
输出一个整数,表示喜悦值总和的最大值
为了博多的加强版。。。
首先这种划分成两个集合,然后满足一些条件会有收益求最优分配方案的题目
一般考虑总收益减去最小割,
理解起来就是本来这些收益全部可以获取,但要分为两个集合的话就是必须要舍弃一些边使得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;
}
原文:http://www.cnblogs.com/qt666/p/6955117.html