zoukankan      html  css  js  c++  java
  • Bzoj 2127: happiness 最小割

    2127: happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 1441  Solved: 695
    [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

     

    Source

     题解:
    最小割。。。
    不会做。。。
    这里Orz一下黄学长的题解:http://hzwer.com/2422.html
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 10012
      4 #define INF 1e9
      5 struct node
      6 {
      7     int begin,end,value,next;
      8 }edge[120010];
      9 int cnt,Head[MAXN+10],dis[MAXN+10],q[MAXN+10],S,T,m,cur[MAXN+10],a[110][110],b[110][110];
     10 bool vis[MAXN+10];
     11 void addedge(int bb,int ee,int vv)
     12 {
     13     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
     14 }
     15 void addedge1(int bb,int ee,int vv)
     16 {
     17     addedge(bb,ee,vv);addedge(ee,bb,vv);
     18 }
     19 int read()
     20 {
     21     int s=0,fh=1;char ch=getchar();
     22     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     23     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     24     return s*fh;
     25 }
     26 int xy(int x,int y){return (x-1)*m+y;}
     27 int BFS()
     28 {
     29     int head,tail,u,v,i;
     30     head=0;tail=1;q[tail]=S;
     31     memset(dis,-1,sizeof(dis));dis[S]=0;
     32     while(head!=tail)
     33     {
     34         head++;if(head==MAXN)head=0;
     35         u=q[head];
     36         for(i=Head[u];i!=-1;i=edge[i].next)
     37         {
     38             v=edge[i].end;
     39             if(edge[i].value>0&&dis[v]<0)
     40             {
     41                 dis[v]=dis[u]+1;
     42                 tail++;if(tail==MAXN)tail=0;
     43                 q[tail]=v;
     44             }
     45         }
     46     }
     47     if(dis[T]<=0)return 0;
     48     else return 1;
     49 }
     50 int DFS(int u,int minflow)
     51 {
     52     int used=0,ans=0,i,v;
     53     if(u==T)return minflow;
     54     for(i=Head[u];i!=-1;i=edge[i].next)
     55     {
     56         v=edge[i].end;
     57         if(edge[i].value>0&&dis[v]==dis[u]+1)
     58         {
     59             ans=minflow-used;
     60             ans=DFS(v,min(ans,edge[i].value));
     61             edge[i].value-=ans;
     62             edge[i^1].value+=ans;
     63             used+=ans;
     64             if(used==minflow)return minflow;
     65         }
     66     }
     67     if(used==0)dis[u]=-1;
     68     return used;
     69 }
     70 int Dinic()
     71 {
     72     int maxflow=0,ans=0,i;
     73     while(BFS()){for(i=1;i<=T;i++)cur[i]=Head[i];ans=DFS(S,INF);if(ans==0)break;maxflow+=ans;}
     74     return maxflow;
     75 }
     76 int main()
     77 {
     78     int n,i,j,ans,p,k;
     79     n=read();m=read();
     80     memset(Head,-1,sizeof(Head));cnt=1;
     81     ans=0;
     82     memset(a,0,sizeof(a));//a数组为每个人选文科的喜悦值.
     83     memset(b,0,sizeof(b));//b数组为每个人选理科的喜悦值.
     84     S=n*m+1;T=S+1;//S为选文科,T为选理科.
     85     for(i=1;i<=n;i++)//单人选文科.
     86     {
     87         for(j=1;j<=m;j++){a[i][j]=read();ans+=a[i][j];a[i][j]*=2;}
     88     }
     89     for(i=1;i<=n;i++)//单人选理科.
     90     {
     91         for(j=1;j<=m;j++){b[i][j]=read();ans+=b[i][j];b[i][j]*=2;}
     92     }
     93     for(i=1;i<n;i++)//不同的两行的人选文科.
     94     {
     95         for(j=1;j<=m;j++){k=read();ans+=k;a[i][j]+=k;a[i+1][j]+=k;addedge1(xy(i,j),xy(i+1,j),k);}
     96     }
     97     for(i=1;i<n;i++)//不同的两行的人选理科.
     98     {
     99         for(j=1;j<=m;j++){k=read();ans+=k;b[i][j]+=k;b[i+1][j]+=k;addedge1(xy(i,j),xy(i+1,j),k);}
    100     }
    101     for(i=1;i<=n;i++)//不同的两列的人选文科.
    102     {
    103         for(j=1;j<m;j++){k=read();ans+=k;a[i][j]+=k;a[i][j+1]+=k;addedge1(xy(i,j),xy(i,j+1),k);}
    104     }
    105     for(i=1;i<=n;i++)//不同的两列的人选理科.
    106     {
    107         for(j=1;j<m;j++){k=read();ans+=k;b[i][j]+=k;b[i][j+1]+=k;addedge1(xy(i,j),xy(i,j+1),k);}
    108     }
    109     for(i=1;i<=n;i++)
    110     {
    111         for(j=1;j<=m;j++){addedge1(S,xy(i,j),a[i][j]);addedge1(xy(i,j),T,b[i][j]);}
    112     }
    113     p=Dinic();
    114     ans*=2;
    115     ans-=p;
    116     printf("%d",ans/2);
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    回调函数: 一定要在函数名前加上 CALLBACK,否则有可能引起内存崩溃!
    win32-api: 让 static 控件中的水平横行,垂直居中。
    Win32-API: 终于能正常的捕获焦点事件: WM_COMMAND、BN_SETFOCUS、EN_SETFOCUS
    FindExecutable:查找与一个指定文件关联在一起的程序的文件名
    ImageMagick: win7 | win8 & uac (用户帐户控制) 注册表的一些事
    ImageMagick: 6.8.3 升级到 6.8.9 遇到的问题
    ImageMagick: DrawImage(Image*,DrawInfo*) 绘制填充图片时卡住的原因分析
    真的无语, 今天遇到一个奇葩的事情: http 会话劫持
    高DPI下界面错乱的解决方法和原理
    关于 HDC 的释放
  • 原文地址:https://www.cnblogs.com/Var123/p/5297935.html
Copyright © 2011-2022 走看看