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.

ISAP!

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

  

BZOJ-2127-happiness(最小割)的更多相关文章

  1. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  2. [置顶] [BZOJ]2127: happiness 最小割

    happiness: Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己 ...

  3. BZOJ 2127: happiness(最小割解决集合划分)

    Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 2350  Solved: 1138[Submit][Status][Discuss] Descript ...

  4. [BZOJ 2127] happiness 【最小割】

    题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建 ...

  5. BZOJ 2127 / Luogu P1646 [国家集训队]happiness (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了 假设跟SSS分在一块是选文科,跟TTT分在一块是选理科,先加上所有的收益,再来考虑如何让需 ...

  6. [国家集训队]happiness 最小割 BZOJ 2127

    题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...

  7. bzoj 2127 happiness【最小割+dinic】

    参考:https://www.cnblogs.com/chenyushuo/p/5144957.html 不得不说这个建图方法真是非常妙啊 假设S点选理,T点选文,a[i][j]为(i,j)选文收益, ...

  8. [bzoj2127]happiness——最小割

    这个题太恶心了...并不想继续做了... 本代码在bzoj上TLE! 大致说一下思路: 建立ST,首先由S连边(S,u,a)a代表学文的分数,连向T(u,T,b)b表示学理的分数,这样构造出了两个人独 ...

  9. spoj 839 OPTM - Optimal Marks&&bzoj 2400【最小割】

    因为是异或运算,所以考虑对每一位操作.对于所有已知mark的点,mark的当前位为1则连接(s,i,inf),否则连(i,t,inf),然后其他的边按照原图连(u,v,1),(v,u,1),跑最大流求 ...

  10. bzoj 2127: happiness

    #include<cstdio> #include<iostream> #include<cstring> #define M 100009 #define inf ...

随机推荐

  1. Windows Form调用R进行绘图并显示

    R软件功能非常强大,可以很好的进行各类统计,并能输出图形.下面介绍一种R语言和C#进行通信的方法,并将R绘图结果显示到WinForm UI界面上. 1 前提准备 安装R软件,需要安装32位的R软件,6 ...

  2. 在js中为图片的src赋值时,src的值不能在开头用 破浪号~

    <img id="aa" src="~/Content/Manager/no01.png" /> document.getElementById(& ...

  3. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  4. SQL Server 2014 Database Mail重复发送邮件特殊案例

    在一数据库服务器(Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64))发现有个作业调用Database Mail发送邮件时, ...

  5. android android BitmapFactory报错OOM

    解决方法:listview中尽量不要使用ImageView作为item的组件 换成view并设background

  6. WordPress + Nginx +PHP+MySQL

    Windows下配置Nginx+php环境 1)php的安装与配置. 直接解压下载好的php包,到D盘wnmp目录(D:\wnmp),这里把解压出来的文件夹重命名成php5.进入文件夹修改php.in ...

  7. Linux环境搭建-在虚拟机中安装Centos7.0

    最近在空闲时间学习Linux环境中各种服务的安装与配置,都属于入门级别的,这里把所有的学习过程记录下来,和大家一起分享. 我的电脑系统是win7,所以我需要在win7上安装一个虚拟机-VMware,然 ...

  8. ultraiso制作大于4GB的镜像的启动盘

    ultraiso这个软件用来做启动盘很方便, 一般linux啦, windows啦, 神马的都用他来做, 但是, 因为ubuntu一般只有1-2GB, win桌面版一般也就3GB左右, 所以不必考虑这 ...

  9. 用字体在网页中画Icon图标

    第一步,下载.IcoMoon网站选择字体图标并下载,解压后将fonts文件夹放在工程目录下.fonts文件夹内有四种格式的字体文件: 注:由于浏览器对每种字体的支持程度不一致,要想在所有浏览器中都显示 ...

  10. 斐波拉契数列(Fibonacci) 的python实现方式

    第一种:利用for循环 利用for循环时,不涉及到函数,但是这种方法对我种小小白来说比较好理解,一涉及到函数就比较抽象了... >>> fibs = [0,1] >>&g ...