【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 }

 

posted @ 2018-01-15 09:54  Kaiser-  阅读(211)  评论(0编辑  收藏  举报