题目描述

  有\(n\times m\)个人,排成一个\(n\times m\)的矩阵。每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。问全班喜悦值的和最大是多少。

  \(n,m\leq 100\)

题解

  先把问题简化,考虑只有两个人,甲选文科的喜悦值为\(a\),甲选理科的喜悦值为\(b\),乙选文科的喜悦值为\(c\),乙选理科的喜悦值为\(d\),两人同时选文科的喜悦值为\(e\),两人同时选理科的喜悦值为\(f\)。

  两个人同时选文或同时选理会有额外喜悦值,这并不太好处理。考虑转化一下。先把两人选文的喜悦值\(a,c\)加上两人同时选文科的喜悦值的一半\(\frac{e}{2}\)。如果只有一人选(即两人选的不同),那么就要减掉\(\frac{e}{2}\)。理科同理。

  这样就是一个网络流的标准模型了。

  最后拿\(a+b+c+d+e+f\)减掉最小割就是答案。

  \(e,f\)有可能是奇数,可以把所有边的容量\(\times 2\),最后再除回来。

  可以得到以下的网络:

  

  多个人的情况和两个人的情况类似,合在一起处理即可。

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<ctime>
  6. #include<utility>
  7. #include<cmath>
  8. #include<functional>
  9. #include<queue>
  10. using namespace std;
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13. typedef pair<int,int> pii;
  14. typedef pair<ll,ll> pll;
  15. void sort(int &a,int &b)
  16. {
  17. if(a>b)
  18. swap(a,b);
  19. }
  20. void open(const char *s)
  21. {
  22. #ifndef ONLINE_JUDGE
  23. char str[100];
  24. sprintf(str,"%s.in",s);
  25. freopen(str,"r",stdin);
  26. sprintf(str,"%s.out",s);
  27. freopen(str,"w",stdout);
  28. #endif
  29. }
  30. int rd()
  31. {
  32. int s=0,c;
  33. while((c=getchar())<'0'||c>'9');
  34. do
  35. {
  36. s=s*10+c-'0';
  37. }
  38. while((c=getchar())>='0'&&c<='9');
  39. return s;
  40. }
  41. int upmin(int &a,int b)
  42. {
  43. if(b<a)
  44. {
  45. a=b;
  46. return 1;
  47. }
  48. return 0;
  49. }
  50. int upmax(int &a,int b)
  51. {
  52. if(b>a)
  53. {
  54. a=b;
  55. return 1;
  56. }
  57. return 0;
  58. }
  59. int v[1000010];
  60. int w[1000010];
  61. int t[1000010];
  62. int h[10010];
  63. int cnt=0;
  64. void add(int x,int y,int z)
  65. {
  66. cnt++;
  67. v[cnt]=y;
  68. w[cnt]=z;
  69. t[cnt]=h[x];
  70. h[x]=cnt;
  71. }
  72. int S,T;
  73. int d[10010];
  74. int e[10010];
  75. int cur[10010];
  76. int num;
  77. int op(int x)
  78. {
  79. return ((x-1)^1)+1;
  80. }
  81. queue<int> q;
  82. void bfs()
  83. {
  84. memset(d,-1,sizeof d);
  85. memcpy(cur,h,sizeof h);
  86. q.push(T);
  87. d[T]=0;
  88. int i,x;
  89. while(!q.empty())
  90. {
  91. x=q.front();
  92. q.pop();
  93. e[d[x]]++;
  94. for(i=h[x];i;i=t[i])
  95. if(w[op(i)]&&d[v[i]]==-1)
  96. {
  97. d[v[i]]=d[x]+1;
  98. q.push(v[i]);
  99. }
  100. }
  101. }
  102. int dfs(int x,int flow)
  103. {
  104. if(x==T)
  105. return flow;
  106. int s=0,c;
  107. int &i=cur[x];
  108. for(;i;i=t[i])
  109. if(d[v[i]]==d[x]-1&&w[i])
  110. {
  111. c=dfs(v[i],min(flow,w[i]));
  112. s+=c;
  113. flow-=c;
  114. w[i]-=c;
  115. w[op(i)]+=c;
  116. if(!flow)
  117. return s;
  118. }
  119. e[d[x]]--;
  120. if(!e[d[x]])
  121. d[S]=num;
  122. e[++d[x]]++;
  123. cur[x]=h[x];
  124. return s;
  125. }
  126. int maxflow()
  127. {
  128. bfs();
  129. int ans=0;
  130. while(d[S]<=num-1)
  131. ans+=dfs(S,0x7fffffff);
  132. return ans;
  133. }
  134. int m1[110][110];
  135. int m2[110][110];
  136. int m3[110][110];
  137. int m4[110][110];
  138. int m5[110][110];
  139. int m6[110][110];
  140. int n,m;
  141. int id(int x,int y)
  142. {
  143. return (x-1)*m+y;
  144. }
  145. int a1[110][110];
  146. int a2[110][110];
  147. int a3[110][110];
  148. int a4[110][110];
  149. int main()
  150. {
  151. open("bzoj2127");
  152. scanf("%d%d",&n,&m);
  153. int i,j;
  154. int sum=0;
  155. for(i=1;i<=n;i++)
  156. for(j=1;j<=m;j++)
  157. {
  158. scanf("%d",&m1[i][j]);
  159. sum+=2*m1[i][j];
  160. a1[i][j]+=2*m1[i][j];
  161. }
  162. for(i=1;i<=n;i++)
  163. for(j=1;j<=m;j++)
  164. {
  165. scanf("%d",&m2[i][j]);
  166. sum+=2*m2[i][j];
  167. a2[i][j]+=2*m2[i][j];
  168. }
  169. for(i=1;i<n;i++)
  170. for(j=1;j<=m;j++)
  171. {
  172. scanf("%d",&m3[i][j]);
  173. sum+=2*m3[i][j];
  174. a1[i][j]+=m3[i][j];
  175. a1[i+1][j]+=m3[i][j];
  176. a3[i][j]+=m3[i][j];
  177. }
  178. for(i=1;i<n;i++)
  179. for(j=1;j<=m;j++)
  180. {
  181. scanf("%d",&m4[i][j]);
  182. sum+=2*m4[i][j];
  183. a2[i][j]+=m4[i][j];
  184. a2[i+1][j]+=m4[i][j];
  185. a3[i][j]+=m4[i][j];
  186. }
  187. for(i=1;i<=n;i++)
  188. for(j=1;j<m;j++)
  189. {
  190. scanf("%d",&m5[i][j]);
  191. sum+=2*m5[i][j];
  192. a1[i][j]+=m5[i][j];
  193. a1[i][j+1]+=m5[i][j];
  194. a4[i][j]+=m5[i][j];
  195. }
  196. for(i=1;i<=n;i++)
  197. for(j=1;j<m;j++)
  198. {
  199. scanf("%d",&m6[i][j]);
  200. sum+=2*m6[i][j];
  201. a2[i][j]+=m6[i][j];
  202. a2[i][j+1]+=m6[i][j];
  203. a4[i][j]+=m6[i][j];
  204. }
  205. num=n*m+2;
  206. S=n*m+1;
  207. T=n*m+2;
  208. for(i=1;i<=n;i++)
  209. for(j=1;j<=m;j++)
  210. {
  211. add(S,id(i,j),a1[i][j]);
  212. add(id(i,j),S,0);
  213. add(id(i,j),T,a2[i][j]);
  214. add(T,id(i,j),0);
  215. }
  216. for(i=1;i<n;i++)
  217. for(j=1;j<=m;j++)
  218. {
  219. add(id(i,j),id(i+1,j),a3[i][j]);
  220. add(id(i+1,j),id(i,j),a3[i][j]);
  221. }
  222. for(i=1;i<=n;i++)
  223. for(j=1;j<m;j++)
  224. {
  225. add(id(i,j),id(i,j+1),a4[i][j]);
  226. add(id(i,j+1),id(i,j),a4[i][j]);
  227. }
  228. int ans=maxflow();
  229. ans=sum-ans;
  230. ans>>=1;
  231. printf("%d\n",ans);
  232. return 0;
  233. }

【BZOJ2127】happiness 网络流的更多相关文章

  1. 【bzoj2127】happiness 网络流最小割

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

  2. bzoj2127: happiness(双倍经验最小割)

    2127: happiness 题目:传送门 题解: 双倍经验美滋滋~ 请看蒟蒻以前写的渣题解...bzoj3894 表示做完自己就最小割了... 代码(直接改的...菜啊): #include< ...

  3. bzoj2127: happiness

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

  4. [bzoj2127]happiness——最小割

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

  5. BZOJ 2127 happiness ——网络流

    [题目分析] 基本上是第一次真正的使用最小割的模型. 同时加上一个数然后最后再减去是处理负数的一种方法. 设立出来最小割的模型然后解方程是一件很重要的事情,建议取一个相对来说比较简单的值带入求解. 这 ...

  6. 【BZOJ2127】happiness(网络流)

    点此看题面 大致题意: 每个人只能在文科与理科中选择一种.选择每种科目会带来不同的喜悦值,如果相邻的两位同学选择了同一种科目则会带来额外的喜悦值.求喜悦值总和的最大值. 网络流 这道题做法显然是网络流 ...

  7. 【BZOJ2127】happiness(最小割)

    [BZOJ2127]happiness(最小割) 题面 Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了, ...

  8. 文理分科 BZOJ3894 & happiness BZOJ2127

    分析: 最小割(一开始我没看出来...后来经过提点,大致理解...),不选则割的思想. 我们先这样考虑,将和选理相关的和S相连,与选文相关的和T相连,如果没有第二问,那么建图就是简单的S连cnt,cn ...

  9. 【bzoj2127】happiness 最大流

    happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 2579  Solved: 1245[Submit][Status][Discuss ...

随机推荐

  1. Python_装饰器进阶_32

    #带参数的装饰器 #500个函数 import time FLAGE = True def timmer_out(flag): def timmer(func): def inner(*args,** ...

  2. H5 69-清除浮动方式四

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. H5 55-行高

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Wannafly挑战赛28

    总结- A-开始觉得是找规律,最开始模拟当时我觉得如果L达到1e9的范围的话,岂不是要加1e9次,模拟也就没有认真写,现在想来,后面由于加的不再是1,而是我前面的值,这样相当了一个斐波那契的类型,而斐 ...

  5. java中流的简单小结

    1.分类 按字节流分: InputStream(输出流)     OutputStream(输入流) 按字符流分: Reader Writer  提示:输入.输出是站在程序的角度而言,所有输入流是“读 ...

  6. jmeter高并发设计方案(转)

    高并发设计方案二(秒杀架构) 优化方向: (1)将请求尽量拦截在系统上游(不要让锁冲突落到数据库上去).传统秒杀系统之所以挂,请求都压倒了后端数据层,数据读写锁冲突严重,并发高响应慢,几乎所有请求都超 ...

  7. vue传参

    <template> <ul> <li v-for="item in list" :key="item.id"> <b ...

  8. 微信小程序错误码参考大全

    开发过程中,会遇到很多微信返回的状态码,鬼知道代表什么意思,现在好了,整理总结了一份状态码,方便大家. 转载:http://www.yiyongtong.com/archives/view-1856- ...

  9. PhpStorm本地断点调试

    一.断点调试php环境搭建 1.检测本地php环境是否安装了Xdebug 在本地输出phpinfo():搜索Xdebug;如下图  如果没有安装,安装操作Xdebug如下: 将phpinfo();的信 ...

  10. Python:matplotlib绘制线条图

    线型图是学习matplotlib绘图的最基础案例.我们来看看具体过程:  下面我们将两条曲线绘制到一个图形里:   可以看到这种方式下,两个线条共用一个坐标轴,并且自动区分颜色. plot方法的核心是 ...