题意:

输入一个h行w列的字符矩阵,草地用“#”表示,洞用"."表示。你可以把草改成洞,每格花费为d,也可以把洞填上草,每格花费为f。最后还需要在草和洞之间修围栏,每条边花费为b。整个矩阵第一行/列和最后一行列必须是草。求最小花费。

分析

这是一个最小割的很典型的题目。

每个洞要么是草地,要么是洞,我们假设草地是S集合,洞是Y集合,然后洞和草之间要建栅栏,也就可以理解为,用最少的花费将S集合和Y集合分开,这就是最小割的模型了。初始时,从s点向所有的草地点连一条边,容量为d,割这些边意味着将这个草地变成洞。把每个洞的点向t连一条边,容量为f,割这些边意味着将这个洞变成草。相邻的两个格子之间u和v,连两条边,u到v和 v到u,容量为b。割u到v这条边意味着u是草,v是洞,在之间建围栏。割v到u的点也类似。

题目还有一个要求,矩阵第一行/列和最后一行/列必须是草,所以,s向这些草连边容量为INF,代表这些边不能割。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <iostream>
  5. #include <queue>
  6.  
  7. using namespace std;
  8. const int maxn=+;
  9. const int maxw=;
  10. const int maxm=;
  11. const int INF=;
  12. struct Dinic{
  13. int head[maxn],Next[maxm],to[maxm],cap[maxm],flow[maxm];
  14. int sz,n,m,s,t;
  15. bool vis[maxn];
  16. int cur[maxn],d[maxn];
  17. void init(int n){
  18. this->n=n;
  19. memset(head,-,sizeof(head));
  20. sz=-;
  21. }
  22. void add_edge(int a,int b,int c){
  23. ++sz;
  24. to[sz]=b;
  25. cap[sz]=c;flow[sz]=;
  26. Next[sz]=head[a];head[a]=sz;
  27. ++sz;
  28. to[sz]=a;
  29. cap[sz]=c;flow[sz]=c;
  30. Next[sz]=head[b];head[b]=sz;
  31. }
  32. bool BFS(){
  33. memset(vis,,sizeof(vis));
  34. queue<int>Q;
  35. vis[s]=;
  36. d[s]=;
  37. Q.push(s);
  38. while(!Q.empty()){
  39. int u=Q.front();Q.pop();
  40. for(int i=head[u];i!=-;i=Next[i]){
  41. int v=to[i];
  42. if(!vis[v]&&cap[i]>flow[i]){
  43. vis[v]=;
  44. d[v]=d[u]+;
  45. Q.push(v);
  46. }
  47. }
  48. }
  49. return vis[t];
  50. }
  51. int DFS(int x,int a){
  52. if(x==t||a==)return a;
  53. int Flow=,f;
  54. for(int& i=cur[x];i!=-;i=Next[i]){
  55. int v=to[i];
  56. if(d[v]==d[x]+&&(f=DFS(v,min(a,cap[i]-flow[i])))>){
  57. Flow+=f;
  58. flow[i]+=f;
  59. flow[i^]-=f;
  60. a-=f;
  61. if(a==)break;
  62. }
  63. }
  64. return Flow;
  65. }
  66. int Maxflow(int s,int t){
  67. this->s=s,this->t=t;
  68. int Flow=;
  69. while(BFS()){
  70. for(int i=;i<=n;i++)
  71. cur[i]=head[i];
  72. Flow+=DFS(s,INF);
  73. }
  74. return Flow;
  75. }
  76. }dinic;
  77. int w,h,d,f,b,T,ans;
  78. char G[maxw][maxw];
  79. int main(){
  80. scanf("%d",&T);
  81. for(int t=;t<=T;t++){
  82. ans=;
  83. scanf("%d%d",&w,&h);
  84. scanf("%d%d%d",&d,&f,&b);
  85. for(int i=;i<=h;i++){
  86. for(int j=;j<=w;j++){
  87. scanf(" %c",&G[i][j]);
  88. if(i==||j==||i==h||j==w){
  89. if(G[i][j]=='.'){
  90. G[i][j]='#';
  91. ans+=f;
  92. }
  93. }
  94. }
  95. }
  96. dinic.init(w*h+);
  97. for(int i=;i<=h;i++){
  98. for(int j=;j<=w;j++){
  99. if(i==||j==||i==h||j==w){
  100. dinic.add_edge(,(i-)*w+j,INF);
  101. }else{
  102. if(G[i][j]=='#'){
  103. dinic.add_edge(,(i-)*w+j,d);
  104. }
  105. if(G[i][j]=='.'){
  106. dinic.add_edge((i-)*w+j,h*w+,f);
  107. }
  108. }
  109. if(i+<=h){
  110. dinic.add_edge((i-)*w+j,i*w+j,b);
  111. dinic.add_edge(i*w+j,(i-)*w+j,b);
  112. }
  113. if(j+<=w){
  114. dinic.add_edge((i-)*w+j,(i-)*w+j+,b);
  115. dinic.add_edge((i-)*w+j+,(i-)*w+j,b);
  116. }
  117. }
  118. }
  119. ans+=dinic.Maxflow(,w*h+);
  120. printf("%d\n",ans);
  121. }
  122. return ;
  123. }

【UVA1515 算法竞赛入门指南】 水塘【最小割】的更多相关文章

  1. 算法竞赛入门经典训练指南——UVA 11300 preading the Wealth

    A Communist regime is trying to redistribute wealth in a village. They have have decided to sit ever ...

  2. (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

    http://www.cnblogs.com/sxiszero/p/3618737.html 下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年 ...

  3. 算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  4. 算法竞赛入门经典 LA 4329(树状数组)

    题意: 一排有着不同能力值的人比赛,规定裁判的序号只能在两人之间,而且技能值也只能在两人之间 问题: <算法竞赛入门经典-训练指南>的分析: 上代码: #include<iostre ...

  5. [刷题]算法竞赛入门经典 3-12/UVa11809

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 题目:算法竞赛入门经典 3-4/UVa11809:Floating-Point Numbers 代码: //UVa11 ...

  6. [刷题]算法竞赛入门经典 3-10/UVa1587 3-11/UVa1588

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 题目:算法竞赛入门经典 3-10/UVa1587:Box 代码: //UVa1587 - Box #include&l ...

  7. [刷题]算法竞赛入门经典 3-7/UVa1368 3-8/UVa202 3-9/UVa10340

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 都是<算法竞赛入门经典(第二版)>的题目,标题上没写(第二版) 题目:算法竞赛入门经典 3-7/UVa13 ...

  8. [刷题]算法竞赛入门经典 3-4/UVa455 3-5/UVa227 3-6/UVa232

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 题目:算法竞赛入门经典 3-4/UVa455:Periodic Strings 代码: //UVa455 #inclu ...

  9. [刷题]算法竞赛入门经典 3-1/UVa1585 3-2/UVa1586 3-3/UVa1225

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO(我也是在网上找到的pdf,但不记得是从哪里搜刮到的了,就重新上传了一遍) PS:第一次写博客分享我的代码,不知道我对c ...

随机推荐

  1. Gixy Nginx 配置分析工具

    项目简介 Gixy 是一款用来分析 Nginx 配置的工具. Gixy 的主要目标是防止安全配置错误,并自动进行缺陷检测. 目前支持的 Python 版本是 2.7 和 3.5+ . 免责声明:Gix ...

  2. #231-D: declaration is not visible outside of function

    通常出现在.h中的函数声明,函数声明中的变量用到了.h当中没有的变量形式,比如特殊定义的结构体

  3. Qt学习之秒表的实现(StopWatch) (转)

    秒表对于我来说并不陌生,在之前自己学习单片机时,实现过秒表和数字钟:基本思路:开启单片机带的定时器,并设置它没10ms溢出一次,分别用三个变量hour,minute,secong记录秒表的时分秒,然后 ...

  4. JFreeChart API 说明(转)

    原地址 http://blog.csdn.net/mike_caoyong/article/details/7338160 JFreeChart目前是最好的java图形解决方案,基本能够解决目前的图形 ...

  5. SAX解析类:SaxHelper

    public class SaxHelper extends DefaultHandler { private Person person; private ArrayList<Person&g ...

  6. Oracle归档与非归档模式

    一.什么是Oracle归档模式 Oracle数据库有联机重做日志,这个日志是记录对数据库所做的修改,比如插入,删除,更新数据等,对这些操作都会记录在联机重做日志里.一般数据库至少要有2个联机重做日志组 ...

  7. USB驱动程序之USB设备驱动程序2鼠标用作键盘学习笔记

    1.usbmouse.c (1)probe函数 在这个probe函数后判断是不是一个鼠标,先得到usb_host_interface结构体,除了端点0外,端点个数如果不是1,返回错误,表示不是自己能支 ...

  8. javascript示例一

    开发工具介绍 前端常用开发工具:sublime.visual Studio Code.HBuilder.Webstorm. 那么大家使用的PCharm跟WebStorm是JetBrains公司推出的编 ...

  9. JavaScript数据类型的检测

    主要有一下四种方法: 1.typeof 2.instanceof 3.constructor 4.Object.prototype.toString.call() 1.typeof 不能具体细分是什么 ...

  10. 12.solr学习速成之dataimport

    solr除了利用solrj建立索引外,还可以由列式数据库hbase触发器添加索引,自动全量或者增量索引关系数据库数据等. dataimport可以配置从任何关系数据库导入索引 1.将jar包拷贝到to ...