题目

最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解,

这块土地是一块矩形的区域,可以纵横划分为N×M块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根

据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第i行第j列的区域,

建造商业区将得到Aij收益,建造工业区将得到Bij收益。另外不同的区域连在一起可以得到额外的收益,即如果区

域(I,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(I,j)的区域,则这块区域能增加k

×Cij收益。经过Tiger.S教授的勘察,收益矩阵A,B,C都已经知道了。你能帮GDOI求出一个收益最大的方案么?

输入格式

输入第一行为两个整数,分别为正整数N和M,分别表示区域的行数和列数;

第2到N+1列,每行M个整数,表示商业区收益矩阵A;

第N+2到2N+1列,每行M个整数,表示工业区收益矩阵B;

第2N+2到3N+1行,每行M个整数,表示相邻额外收益矩阵C。

任何数字不超过1000”的限制

输出格式

输出只有一行,包含一个整数,为最大收益值。

输入样例

3 3

1 2 3

4 5 6

7 8 9

9 8 7

6 5 4

3 2 1

1 1 1

1 3 1

1 1 1

输出样例

81

提示

【数据规模】

对于100%的数据有N,M≤100

题解

类似BZOJ2127happiness

上一次似乎没有写博,,

一个经典的最小割模型,每个人有两个选择,每个选择有不同收益,当一些人选择相同时会有额外的收益,求最大收益

用一个这样的图:

这个图有两种割法

设二人同选\(A\)的额外收益为\(w_a\),同选\(B\)为\(w_b\)

①当二者选择不同时,除了没选的收益外,会付出额外代价\(w_a + w_b\)

对应的图中代价,要割掉不同侧的边,以及中间的一条边

\[x_1 + x_3 + x_6
\]

\[x_2 + x_4 + x_5
\]

②选择相同时,除了

对应图中,割掉一侧的边即可

\[x_1 + x_5
\]

\[x_2 + x_6
\]

那么有:

\[x_1 + x_3 + x_6 = w_a + w_b
\]

\[x_2 + x_4 + x_5 = w_a + w_b
\]

\[x_1 + x_5 = w_b
\]

\[x_2 + x_6 = w_a
\]

似乎有多解,我们不妨设:

\[x_1 = x_5
\]

\[x_2 = x_6
\]

即可得到一组比较特殊的解:

\[x_1 = x_5 = \frac{w_b}{2} \qquad x_2 = x_6 = \frac{w_a}{2} \qquad x_3 = x_4 = \frac{w_a + w_b}{2}
\]

那么最小割即为在提前拥有所有收益后必须付出的最小代价了

具体建图中,我们通常将边权乘\(2\)变为整数

回到这题,建图就很裸了

不过这题是不同产生收益,我们二分染色一下,然后对于其中一种颜色的点\(AB\)交换即可

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #define LL long long int
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
  10. using namespace std;
  11. const int maxn = 10005,maxm = 200005,N = 105,INF = 1000000000;
  12. inline int read(){
  13. int out = 0,flag = 1; char c = getchar();
  14. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  15. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  16. return out * flag;
  17. }
  18. int A[N][N],B[N][N],C[N][N],id[N][N],X[4] = {0,0,-1,1},Y[4] = {-1,1,0,0};
  19. int n,m,S,T;
  20. int h[maxn],ne = 2;
  21. struct EDGE{int to,nxt,f;}ed[maxm];
  22. inline void build(int u,int v,int w){
  23. ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
  24. ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
  25. }
  26. int d[maxn],vis[maxn],used[maxn],cur[maxn],now;
  27. int q[maxn],head,tail;
  28. inline bool bfs(){
  29. q[head = tail = 1] = S; vis[S] = now; d[S] = 0;
  30. int u;
  31. while (head <= tail){
  32. u = q[head++];
  33. Redge(u) if (ed[k].f && vis[to = ed[k].to] != now){
  34. d[to] = d[u] + 1; vis[to] = now;
  35. if (to == T) return true;
  36. q[++tail] = to;
  37. }
  38. }
  39. return vis[T] == now;
  40. }
  41. int dfs(int u,int minf){
  42. if (u == T || !minf) return minf;
  43. int flow = 0,f,to;
  44. if (used[u] != now) cur[u] = h[u],used[u] = now;
  45. for (int& k = cur[u]; k; k = ed[k].nxt)
  46. if (vis[to = ed[k].to] == now && d[to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
  47. ed[k].f -= f; ed[k ^ 1].f += f;
  48. flow += f; minf -= f;
  49. if (!minf) break;
  50. }
  51. return flow;
  52. }
  53. int maxflow(){
  54. int flow = 0; now = 1;
  55. while (bfs()){
  56. flow += dfs(S,INF);
  57. now++;
  58. }
  59. return flow;
  60. }
  61. int main(){
  62. n = read(); m = read(); S = 0; T = m * n + 1;
  63. int ans = 0;
  64. REP(i,n) REP(j,m) A[i][j] = read(),ans += A[i][j],A[i][j] <<= 1;
  65. REP(i,n) REP(j,m) B[i][j] = read(),ans += B[i][j],B[i][j] <<= 1;
  66. REP(i,n) REP(j,m) C[i][j] = read();
  67. REP(i,n) REP(j,m) id[i][j] = (i - 1) * m + j;
  68. REP(i,n) REP(j,m){
  69. int x,y,tmp;
  70. if ((i & 1) ^ (j & 1)){
  71. for (int k = 0; k < 4; k++){
  72. x = i + X[k];
  73. y = j + Y[k];
  74. if (x < 1 || y < 1 || x > n || y > m) continue;
  75. tmp = C[i][j] + C[x][y]; ans += tmp << 1;
  76. A[i][j] += tmp; B[i][j] += tmp;
  77. A[x][y] += tmp; B[x][y] += tmp;
  78. build(id[i][j],id[x][y],tmp << 1);
  79. build(id[x][y],id[i][j],tmp << 1);
  80. }
  81. }
  82. }
  83. REP(i,n) REP(j,m){
  84. if ((i & 1) ^ (j & 1)){
  85. build(S,id[i][j],A[i][j]);
  86. build(id[i][j],T,B[i][j]);
  87. }
  88. else {
  89. build(S,id[i][j],B[i][j]);
  90. build(id[i][j],T,A[i][j]);
  91. }
  92. }
  93. printf("%d\n",ans - (maxflow() >> 1));
  94. return 0;
  95. }

BZOJ2132 圈地计划 【最小割】的更多相关文章

  1. 【BZOJ2132】圈地计划 最小割

    [BZOJ2132]圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地. ...

  2. [BZOJ]2132: 圈地计划 最小割

    圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一 ...

  3. BZOJ 2131 圈地计划(最小割+黑白染色)

    类似于happiness的一道题,容易想到最小割的做法. 但是不同的是那一道题是相邻的如果相同则有收益,这题是相邻的不同才有收益. 转化到建图上面时,会发现,两个相邻的点连的边容量会是负数.. 有一种 ...

  4. bzoj2132圈地计划

    bzoj2132圈地计划 题意: 一块土地可以纵横划分为N×M块小区域.于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益.而如果区域(i,j)相邻(相邻是指两个格子有公共边 ...

  5. bzoj2132: 圈地计划(无比强大的最小割)

    2132: 圈地计划 题目:传送门 简要题意: 给出一个矩阵,一共n*m个点,并给出三个收益矩阵.A矩阵表示这个点建A的可取收益,B矩阵表示这个点建B的可取收益,C矩阵表示如果相邻(有且仅有一条公共边 ...

  6. bzoj2132: 圈地计划

    要分成两坨对吧.. 所以显然最小割 但是不兹辞啊.. 最小割是最小的啊 求最大费用怎么玩啊 那咱们就把所有费用都加起来,减掉一个最小的呗 但是两个属于不同集合的点贡献的价值是负的啊 网络流怎么跑负的啊 ...

  7. bzoj2132: 圈地计划(最小割)

    传送门 看来以后见到矩形就要黑白染色冷静一下了…… 首先,如果它的要求时候相邻的选择相同,那么就是和这一题一样了->这里 然后考虑不同的要怎么做 那就把矩形黑白染色一下吧 然后令其中一种颜色的A ...

  8. 【BZOJ2132】圈地计划(最小割)

    [BZOJ2132]圈地计划(最小割) 题面 BZOJ 题解 对我而言,不可做!!! 所以我膜烂了ZSY大佬 他的博客写了怎么做... 这,,...太强啦!! 完全想不到黑白染色之后反着连边 然后强行 ...

  9. 【bzoj2132】圈地计划 网络流最小割

    题目描述 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一块矩形的区域,可以纵横划 ...

随机推荐

  1. unsigned __int64 打印方法

    原文出处 long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647. 而unsigned范围是[0,2^32),即0~4294967295.也就是说,常规的 ...

  2. C#的接口基础教程之七 覆盖虚接口

    有时候我们需要表达一种抽象的东西,它是一些东西的概括,但我们又不能真正的看到它成为一个实体在我们眼前出现,为此面向对象的编程语言便有了抽象类的概念.C#作为一个面向对象的语言,必然也会引入抽象类这一概 ...

  3. 换了台电脑tomcat自己运行没问题,eclipse中配置tomcat开启了浏览器却404错误解决

    如果发现下图中 apache tomcat 的Overview 视图中发现 Server Locations 灰色显示 那么首先需要配置好TomCat的TOMCAT_HOME 和 CATALINA_H ...

  4. SummerVocation_Learning--java的String类方法总结

    壹: public char charAt(int index),返回字符串中第index个字符. public int length(), 返回字符串长度. public int indexOf(S ...

  5. 对比传统方式访问数据库和SpringData访问数据库

    我们在写代码的时候应该一边写一边测试,这样的话可以尽快的找到错误,在代码写多了之后去找错误的话不容易给错误定位 传统方式访问数据库 1:创建一个Maven web项目 2:修改pom.xml为以下内容 ...

  6. 二十二、MySQL 正则表达式

    MySQL 正则表达式 在前面的章节我们已经了解到MySQL可以通过 LIKE ...% 来进行模糊匹配. MySQL 同样也支持其他正则表达式的匹配, MySQL中使用 REGEXP 操作符来进行正 ...

  7. vue 项目中使用mock假数据实现前后端分离

    也是查了很多的资料,整理出来.实现了前后端的分离,用到的技术vue-cli,webpack,node,json-server.首先全局安装json-server cnpm i json-server ...

  8. 用jq给img添加error事件

    <img src="xxxx.jpg" alt="" /> <script> $(document).ready(function(){ ...

  9. javascript sprintf方法

    转载自: http://demon.tw/programming/javascript-sprintf.html function str_repeat(i, m) { for (var o = [] ...

  10. Codeforces Round #271 (Div. 2) D Flowers【计数dp】

    D. Flowers time limit per test 1.5 seconds memory limit per test 256 megabytes input standard input ...