题面传送门

题目大意:给你一个网格图,每个格子都有$a_{ij}$的代价和$b_{ij}$的回报,对于格子$ij$,想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通的格子都付出代价,求最大的回报-代价

好神的一道题,%%%jr

想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通的格子都付出代价

所以把棋盘像国际象棋一样黑白交叉染色,原图就变成了一个类似于二分图的东西

每个格子都拆成$2$个点

对于白格子,源点$S$向$W1$连流量为$a_{ij}$的边,$W1$向$W2$连流量为$b_{ij}$的边,$W2$向白格子周围四个黑格子的$B2$连流量为$inf$的边

对于黑格子,$B2$向汇点$T$连流量为$a_{ij}$的边,$B1$向$B2$连流量为$b_{ij}$的边,周围四个白格子的$W1$向$B1$连流量为$inf$的边

然后跑最大流,答案就是总回报-最大流

为什么要这么建边?我们可以对割进行分析

如果一个白格子的代价边$a_{ij}$被割掉了,说明这个格子带来的回报$\geq$代价,被归到了$T$集合里,此时流量$=$代价,统计答案时会加上回报$-$代价

如果一个白格子的代价边$a_{ij}$没被割掉,说明这个格子带来的回报$<$代价,被归到了$S$集合里,此时流量$=$回报,统计答案时会把这部分回报去掉

黑格子也是同理

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define N1 5010
  5. #define M1 30010
  6. #define L1 55
  7. using namespace std;
  8. const int inf=0x3f3f3f3f;
  9.  
  10. int gint()
  11. {
  12. int ret=,fh=;char c=getchar();
  13. while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
  14. while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
  15. return ret*fh;
  16. }
  17. struct Edge{
  18. int to[M1<<],nxt[M1<<],flow[M1<<],head[N1],cte;
  19. void ae(int u,int v,int f)
  20. {
  21. cte++; to[cte]=v; nxt[cte]=head[u];
  22. head[u]=cte; flow[cte]=f;
  23. }
  24. }e;
  25.  
  26. int dep[N1],que[M1],cur[N1],n,m,hd,tl,S,T;
  27. int bfs()
  28. {
  29. int x,j,v;
  30. memset(dep,-,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
  31. hd=,tl=; que[++tl]=S; dep[S]=;
  32. while(hd<=tl)
  33. {
  34. x=que[hd++];
  35. for(j=e.head[x];j;j=e.nxt[j])
  36. {
  37. v=e.to[j];
  38. if( dep[v]==- && e.flow[j]> )
  39. {
  40. dep[v]=dep[x]+;
  41. que[++tl]=v;
  42. }
  43. }
  44. }
  45. return dep[T]!=-;
  46. }
  47. int dfs(int x,int limit)
  48. {
  49. int j,v,flow,ans=;
  50. if(!limit||x==T) return limit;
  51. for(j=cur[x];j;j=e.nxt[j])
  52. {
  53. v=e.to[j]; cur[x]=j;
  54. if( dep[v]==dep[x]+ && (flow=dfs(v,min(limit,e.flow[j]))) )
  55. {
  56. e.flow[j]-=flow; limit-=flow;
  57. e.flow[j^]+=flow; ans+=flow;
  58. if(!limit) break;
  59. }
  60. }
  61. return ans;
  62. }
  63. int Dinic()
  64. {
  65. int mxflow=,j,v,ans=;
  66. while(bfs())
  67. mxflow+=dfs(S,inf);
  68. return mxflow;
  69. }
  70.  
  71. int xx[]={-,,,},yy[]={,,,-};
  72. int a[L1][L1],b[L1][L1],id[L1][L1];
  73. inline int check(int x,int y){return (x<||y<||x>n||y>m)?:;}
  74.  
  75. int main()
  76. {
  77. scanf("%d%d",&n,&m);
  78. int i,j,x,y,k,tot=n*m,sum=; e.cte=; S=; T=tot+tot+;
  79. for(i=;i<=n;i++) for(j=;j<=m;j++) a[i][j]=gint();// sum+=v[i][j];
  80. for(i=;i<=n;i++) for(j=;j<=m;j++) b[i][j]=gint(), id[i][j]=(i-)*m+j, sum+=b[i][j];
  81. for(i=;i<=n;i++) for(j=;j<=m;j++)
  82. {
  83. x=id[i][j];
  84. if((i+j)&){
  85. e.ae(S,x,a[i][j]); e.ae(x,S,);
  86. e.ae(x,x+tot,b[i][j]); e.ae(x+tot,x,);
  87. for(k=;k<;k++)
  88. {
  89. if(!check(i+xx[k],j+yy[k])) continue;
  90. y=id[i+xx[k]][j+yy[k]];
  91. e.ae(x+tot,y+tot,inf); e.ae(y+tot,x+tot,);
  92. }
  93. }else{
  94. e.ae(x+tot,T,a[i][j]); e.ae(T,x+tot,);
  95. e.ae(x,x+tot,b[i][j]); e.ae(x+tot,x,);
  96. for(k=;k<;k++)
  97. {
  98. if(!check(i+xx[k],j+yy[k])) continue;
  99. y=id[i+xx[k]][j+yy[k]];
  100. e.ae(y,x,inf); e.ae(x,y,);
  101. }
  102. }
  103. }
  104. printf("%d\n",sum-Dinic());
  105. return ;
  106. }

BZOJ 3774 最优选择 (最小割+二分图)的更多相关文章

  1. BZOJ 3774: 最优选择( 最小割 )

    最小割...二分染色然后把颜色不同的点的源汇反过来..然后就可以做了. 某个点(x,y): S->Id(x,y)(回报), Id(x,y)->T(代价), Id(i,j)&& ...

  2. [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...

  3. 【BZOJ3774】最优选择 最小割

    [BZOJ3774]最优选择 Description 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择 ...

  4. 【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题

    Description 给定一个 \(n~\times~m\) 的矩阵,每个位置有一个正整数,选择一些互不相邻的数,最大化权值和 Limitation \(1~\leq~n,~m~\leq~100\) ...

  5. BZOJ 1934 Vote 善意的投票(最小割+二分图)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1934 题目大意: 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题 ...

  6. BZOJ 2039 人员雇佣 二元关系 最小割

    题面太长了,请各位自行品尝—>人员雇佣 分析: 借用题解的描述: a.选择每个人有一个代价Ai b.如果有两个人同时选择就可以获得收益Ei,j c.如果一个人选择另一个不选会产生代价Ei,j 这 ...

  7. POJ3308 Paratroopers(最小割/二分图最小点权覆盖)

    把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...

  8. BZOJ 1497: [NOI2006]最大获利 最小割

    1497: [NOI2006]最大获利 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1497 Description 新的技术正冲击着手 ...

  9. bzoj 1391 [Ceoi2008]order(最小割)

    [题意] 有n个有偿工作选做,m个机器,完成一个工作需要若干个工序,完成每个工序需要一个机器,对于一个机器,在不同的工序有不同的租费,但买下来的费用只有一个.问最大获益. [思路] 对于工作和机器建点 ...

随机推荐

  1. HDU 1515

    简单题,直接用STACK模拟整个过程. 模拟出栈时,应注意保护现场,等到递归完成后返回. #include <iostream> #include <string.h> #in ...

  2. Thread interrupt表示什么

    Thread interrupt表示什么 学习了:https://www.zhihu.com/question/41048032?sort=created 学习了:http://blog.csdn.n ...

  3. IT人才异军突起 有招网引领业界精英

    随着网络时代的到来,IT人才也在不断的增长.当然,不仅IT行业对IT人才需求旺盛.部分传统企业为打造互联网时代下的企业,也在紧锣密鼓的招聘IT人才.据统计.眼下我国各地对IT人才的需求已经占领总体人才 ...

  4. 【剑指offer】Q19:二叉树的镜像

    def MirroRecursively(root): # root is None or just one node, return root if None == root or None == ...

  5. luogu2508 [HAOI2008]圆上的整点

    题目大意 给出\(r\),求圆\(x^2+y^2=r^2\)上坐标均为整数的点数.\(n<=2,000,000,000\) 总体思路 我们看到这个数据大小,还是个数学题,想到这个的时间复杂度应当 ...

  6. c17---指针

    // // main.c // 指针基本概念 #include <stdio.h> // 基本数据类型作为函数的参数是值传递, 在函数中修改形参的值不会影响到外面实参的值 void cha ...

  7. ReflectionSugar 通用反射类

    http://www.cnblogs.com/sunkaixuan/p/4635710.html

  8. Node.js:文件系统

    ylbtech-Node.js:文件系统 1.返回顶部 1. Node.js 文件系统 Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API. Node 导入文件系统模块(fs)语 ...

  9. Node.js:模块系统

    ylbtech-Node.js:模块系统 1.返回顶部 1. Node.js模块系统 为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统. 模块是Node.js 应用程序的 ...

  10. html页面、canvas导出图片

    背景:项目现场提出将一个html做的图形页面导出为一张图片的需求,在网上搜了一下,发现都不是很全面,所以综合了很多大神的帖子,自己再次封装,以适用项目需求. 所需js库:html2canvas.js( ...