zoukankan      html  css  js  c++  java
  • 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 2
    1 1
    100 110
    1
    1000

    Sample Output

    1210
    【样例说明】
    两人都选理,则获得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
    ",valt-(int)F);
      return 0;
    }
    
  • 相关阅读:
    iOS开发——网络篇——文件下载(NSMutableData、NSFileHandle、NSOutputStream)和上传、压缩和解压(三方框架ZipArchive),请求头和请求体格式,断点续传Range
    聚类_七月算法4月机器学习班第10次课程笔记
    codejam环境熟悉—Minimum Scalar Product
    STL源码剖析读书笔记--第6章&第7章--算法与仿函数
    STL源码分析读书笔记--第5章--关联式容器
    STL源码剖析读书笔记--第四章--序列式容器
    STL源码分析读书笔记--第二章--空间配置器(allocator)
    树莓PI上跑爬虫
    树莓PI安装jdk1.8,ant,maven【转】
    myeclipse10 安装 testng插件
  • 原文地址:https://www.cnblogs.com/qt666/p/6955117.html
Copyright © 2011-2022 走看看