Bzoj 2127: happiness 最小割
2127: happiness
Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 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
1 1
100 110
1
1000
Sample Output
1210
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数
【样例说明】
两人都选理,则获得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 }