zoukankan      html  css  js  c++  java
  • 【bzoj2127】happiness 最大流

    happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 2579  Solved: 1245
    [Submit][Status][Discuss]

    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

    和文理分科差不多

    利用最小割考虑。

    对于原图中所有相邻的两个人A,B,我们建边:

    s->A:cost[A文]+c[文][A][B]/2,s->B:cost[B文]+c[文][A][B]/2;

    A->t:cost[A理]+c[理][A][B]/2,B->t:costB[理]+c[理][A][B]/2;

    A<–>B:c[文][A][B]/2+c[理][A][B]/2

    这样会出现两种割,分别对应两种相同,一种选文一种选理。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define T 10001
     5 #define inf 0x7fffffff
     6 #define FOR for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     7 #define rep(x,y) for(int i=1;i<=x;i++)for(int j=1;j<=y;j++)
     8 #define ll long long
     9 using namespace std;
    10 int n,m,ans,tot,cnt=1,head[10002],h[10002];
    11 int a[101][101],b[101][101],color[101][101],mark[101][101];
    12 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
    13 struct data{int to,next,v;}e[300001];
    14 void ins(int u,int v,int w)
    15 {cnt++;e[cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;}
    16 void insert(int u,int v,int w)
    17 {ins(u,v,w);ins(v,u,0);}
    18 void ins2(int u,int v,int w)
    19 {ins(u,v,w);ins(v,u,w);}
    20 bool bfs()
    21 {
    22      int q[10005],t=0,w=1,i,now;
    23      memset(h,-1,sizeof(h));
    24      q[0]=h[0]=0;
    25      while(t!=w)
    26      {
    27             now=q[t];t++;if(t==10001)t=0;
    28             for(i=head[now];i;i=e[i].next)
    29             {
    30                   if(e[i].v&&h[e[i].to]<0)
    31                         {h[e[i].to]=h[now]+1;q[w++]=e[i].to;if(w==10001)w=0;}
    32              }
    33      }
    34      if(h[T]==-1)return 0;return 1;
    35      }
    36 int dfs(int x,int f)
    37 {
    38     if(x==T)return f;
    39     int w,used=0;
    40     for(int i=head[x];i;i=e[i].next)
    41     {
    42             if(e[i].v&&h[e[i].to]==h[x]+1)
    43             {
    44                 w=f-used;
    45                 w=dfs(e[i].to,min(w,e[i].v));   
    46                 e[i].v-=w;e[i^1].v+=w;
    47                 used+=w;if(used==f)return f;                      
    48                 }
    49             }
    50     if(!used)h[x]=-1;
    51     return used;
    52     }
    53 void dinic(){while(bfs())ans+=dfs(0,inf);}
    54 void build()
    55 {
    56     int x;
    57     rep(n-1,m)
    58     {
    59        scanf("%d",&x);tot+=x;
    60        a[i][j]+=x;a[i+1][j]+=x;
    61        ins2(mark[i][j],mark[i+1][j],x);
    62        }
    63     rep(n-1,m)
    64     {
    65        scanf("%d",&x);tot+=x;
    66        b[i][j]+=x;b[i+1][j]+=x;
    67        ins2(mark[i][j],mark[i+1][j],x);
    68        }
    69     rep(n,m-1)
    70     {
    71        scanf("%d",&x);tot+=x;
    72        a[i][j]+=x;a[i][j+1]+=x;
    73        ins2(mark[i][j],mark[i][j+1],x);
    74        }
    75     rep(n,m-1)
    76     {
    77        scanf("%d",&x);tot+=x;
    78        b[i][j]+=x;b[i][j+1]+=x;
    79        ins2(mark[i][j],mark[i][j+1],x);
    80        }
    81     FOR{
    82            insert(0,mark[i][j],a[i][j]);
    83            insert(mark[i][j],T,b[i][j]);
    84        }
    85 }
    86 int main()
    87 {
    88     scanf("%d%d",&n,&m);
    89     FOR scanf("%d",&a[i][j]),tot+=a[i][j],a[i][j]<<=1;
    90     FOR scanf("%d",&b[i][j]),tot+=b[i][j],b[i][j]<<=1;
    91     FOR mark[i][j]=(i-1)*m+j;
    92     build();dinic();
    93     printf("%d",tot-(ans>>1));
    94 }
  • 相关阅读:
    DC中为什么要用Uniquify?
    hdu 1596 find the safest road
    hdu2112 HDU Today
    hdu 2066 一个人的旅行
    poj 3026 Borg Maze
    poj 1979 Red and Black
    poj 1321 棋盘问题
    hdu 1010 Tempter of the Bone
    hdu 4861 Couple doubi
    codeforces584B Kolya and Tanya
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8286787.html
Copyright © 2011-2022 走看看