首页 > 移动平台 > 详细

BZOJ-2127-happiness(最小割)

时间:2017-01-06 22:14:05      阅读:531      评论:0      收藏:0      [点我收藏+]

2127: happiness(题解)

Time Limit: 51 Sec  Memory Limit: 259 MB
Submit: 1806  Solved: 875

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的非负整数
 
【分析】
非常烦的建图过程,最小割(二选一经典模型)。
建图:

对于原图中所有相邻的两个人A,B,我们建边:(S源,T汇)

S->A:文A+文AB/2

S->B:文B+文AB/2

A->T:理A+理AB/2

B->T:理B+理AB/2

A<–>B:文AB/2+理AB/2

但是,为了保持精度准确,我们先建图时所有边*2,最后ans再/2.

技术分享
  1 #include<iostream>
  2 #include<fstream>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<string>
  6 #include<vector>
  7 #include<queue>
  8 #include<deque>
  9 #include<utility>
 10 #include<map>
 11 #include<set>
 12 #include<cmath>
 13 #include<cstdlib>
 14 #include<ctime>
 15 #include<functional>
 16 #include<sstream>
 17 #include<cstring>
 18 #include<bitset>
 19 #include<stack>
 20 using namespace std;
 21 
 22 int n,m,s,t,cnt,x,y,z,sum;
 23 struct sdt
 24 {
 25     int cap,flow,u,v;
 26 }e[500005];
 27 int nxt[500005],fir[10005],d[10005],par[10005],num[10005],cur[10005];
 28 int wk[105][105],lk[105][105],kkk[105][105];
 29 bool vis[10005];
 30 
 31 int read()
 32 {
 33     int x=0;char c=getchar();
 34     while(c<48||c>57)c=getchar();
 35     while(c>47&&c<58)x*=10,x+=c-48,c=getchar();
 36     return x;
 37 }
 38 
 39 void add(int x,int y,int z)
 40 {
 41     e[++cnt].u=x;e[cnt].v=y;e[cnt].cap=z;e[cnt].flow=0;
 42     nxt[cnt]=fir[x];fir[x]=cnt;
 43 }
 44 
 45 void bfs()
 46 {
 47     memset(vis,0,sizeof(vis));
 48     memset(d,0,sizeof(d));
 49     queue<int>q;
 50     d[t]=0;
 51     vis[t]=1;
 52     q.push(t);
 53     while(!q.empty())
 54     {
 55         int k=q.front();
 56         q.pop();
 57         for(int i=fir[k];i;i=nxt[i])
 58         {
 59             if(!vis[e[i].v] && e[i].cap==0)
 60             {
 61                 vis[e[i].v]=1;
 62                 d[e[i].v]=d[k]+1;
 63                 q.push(e[i].v);
 64             }
 65         }
 66     }
 67 }
 68 
 69 int agument()
 70 {
 71     int p=t;
 72     int ans=2147483647;
 73     while(p!=s)
 74     {
 75         ans=min(ans,e[par[p]].cap-e[par[p]].flow);
 76         p=e[par[p]].u;
 77     }
 78     p=t;
 79     while(p!=s)
 80     {
 81         e[par[p]].flow+=ans;
 82         e[par[p]^1].flow-=ans;
 83         p=e[par[p]].u;
 84     }
 85     return ans;
 86 }
 87 
 88 int isap()
 89 {
 90     memset(num,0,sizeof(num));
 91     int flow=0;
 92     for(int i=1;i<=t;i++)
 93     {
 94         num[d[i]]++;
 95         cur[i]=fir[i];
 96     }
 97     int p=s;
 98     while(d[s]<t)
 99     {
100         if(p==t)
101         {
102             flow+=agument();
103             p=s;
104         }
105         bool ok=0;
106         for(int i=cur[p];i;i=nxt[i])
107         {
108             if(e[i].cap>e[i].flow && d[p]==d[e[i].v]+1)
109             {  
110                 ok=1;  
111                 par[e[i].v]=i;  
112                 cur[p]=i;  
113                 p=e[i].v;  
114                 break;  
115             }  
116         }
117         if(!ok)
118         {
119             int mn=t-1;
120             for(int i=fir[p];i;i=nxt[i])
121             {
122                 if(e[i].cap>e[i].flow)mn=min(mn,d[e[i].v]);
123             }
124             if(--num[d[p]]==0)break;
125             num[d[p]=mn+1]++;
126             cur[p]=fir[p];
127             if(p!=s)p=e[par[p]].u;
128         }
129     }
130     return flow;
131 }
132 
133 int main()
134 {
135     n=read();m=read();;
136     memset(nxt,0,sizeof(nxt));
137     memset(fir,0,sizeof(fir));
138     cnt=1;
139     s=1;
140     t=n*m+2;
141     for(int i=1;i<=n;i++)
142     {
143         for(int j=1;j<=m;j++)
144         {
145             wk[i][j]=read();
146             sum+=wk[i][j];
147             add(s,(i-1)*m+j+1,wk[i][j]*2);
148             add((i-1)*m+j+1,s,0);
149         }
150     }
151     for(int i=1;i<=n;i++)
152     {
153         for(int j=1;j<=m;j++)
154         {
155             lk[i][j]=read();
156             sum+=lk[i][j];
157             add((i-1)*m+j+1,t,lk[i][j]*2);
158             add(t,(i-1)*m+j+1,0);
159         }
160     }
161     for(int i=1;i<=n-1;i++)
162     {
163         for(int j=1;j<=m;j++)
164         {
165             x=read();
166             sum+=x;
167             kkk[i][j]=x;
168             add(s,(i-1)*m+j+1,x);
169             add((i-1)*m+j+1,s,0);
170             add(s,i*m+j+1,x);
171             add(i*m+j+1,s,0);
172         }
173     }
174     for(int i=1;i<=n-1;i++)
175     {
176         for(int j=1;j<=m;j++)
177         {
178             x=read();
179             sum+=x;
180             add((i-1)*m+j+1,t,x);
181             add(t,(i-1)*m+j+1,0);
182             add(i*m+j+1,t,x);
183             add(t,i*m+j+1,0);
184             add(1+(i-1)*m+j,1+i*m+j,kkk[i][j]+x);
185             add(1+i*m+j,1+(i-1)*m+j,kkk[i][j]+x);
186         }
187     }
188     memset(kkk,0,sizeof(kkk));
189     for(int i=1;i<=n;i++)
190     {
191         for(int j=1;j<=m-1;j++)
192         {
193             x=read();
194             sum+=x;
195             kkk[i][j]=x;
196             add(s,(i-1)*m+j+1,x);
197             add((i-1)*m+j+1,s,0);
198             add(s,(i-1)*m+j+2,x);
199             add((i-1)*m+j+2,s,0);
200         }
201     }
202     for(int i=1;i<=n;i++)
203     {
204         for(int j=1;j<=m-1;j++)
205         {
206             x=read();
207             sum+=x;
208             add((i-1)*m+j+1,t,x);
209             add(t,(i-1)*m+j+1,0);
210             add((i-1)*m+j+2,t,x);
211             add(t,(i-1)*m+j+2,0);
212             add(1+(i-1)*m+j,(i-1)*m+j+2,kkk[i][j]+x);
213             add((i-1)*m+j+2,1+(i-1)*m+j,kkk[i][j]+x);
214         }
215     }
216     bfs();
217     printf("%d\n",sum-isap()/2);
218     return 0;
219 }
ISAP实现

 

BZOJ-2127-happiness(最小割)

原文:http://www.cnblogs.com/winmt/p/6257039.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!