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

 

posted @ 2016-03-20 15:40  微弱的世界  阅读(153)  评论(0编辑  收藏  举报