题目大意:有一块地,分成nxm块。有的块上长着草,有的块上是荒地。将任何一块长着草的块上的草拔掉都需要花费d个力气,往任何一块荒地上种上草都需要花费f个力气,在草和荒地之间架一个篱笆需要花费b个力气,如果一块草地四周都是荒地,则得花掉4b个力气。现在,要求最外一圈都种上草,草地与荒地之间要用篱笆隔开,最少需要花费多少个力气?

题目分析:有篱笆要把草地和荒地隔开意味着把所有的块分成两个“阵营”。增加源点和汇点,用源点s代表草地“阵营”头领,汇点t代表荒地“阵营”头领,在初始时,从s向所有的草地(在边界处的除外)连一条弧,容量为d,表示该块草地要背叛头领s投奔敌人的代价;从所有的荒地向汇点连一条弧,容量为f,表示该块荒地放弃头领t的代价;对于任意一个块u,向所有与它相邻的v连一条弧,容量为b,表示u与v对立的代价。我们要做的就是用最少的代价这些块分成两个“阵营”,实际上就是求最小割。

CP:第一次用ISAP来写网络流。。。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
# include<cstring>
# include<iostream>
using namespace std;const int INF=1<<30;
const int maxn=2505;int n,m;
char p[60][60];struct Edge
{int fr,to,cap,fw;Edge(int fr,int to,int cap,int fw){this->fr=fr;this->to=to;this->cap=cap;this->fw=fw;}
};
struct ISAP
{vector<Edge>edges;vector<int>G[maxn];int d[maxn],gap[maxn],p[maxn];int n,s,t,vis[maxn],cur[maxn];void init(int n){this->n=n;edges.clear();for(int i=0;i<n;++i) G[i].clear();}void addEdge(int u,int v,int cap){edges.push_back(Edge(u,v,cap,0));edges.push_back(Edge(v,u,0,0));int m=edges.size();G[u].push_back(m-2);G[v].push_back(m-1);}void bfs(int u){memset(vis,0,sizeof(vis));d[u]=0;queue<int>q;q.push(u);vis[u]=1;while(!q.empty()){int x=q.front();q.pop();for(int i=0;i<G[x].size();++i){Edge &e=edges[G[x][i]];if(e.cap>0) continue;int v=edges[G[x][i]^1].fr;if(!vis[v]){vis[v]=1;d[v]=d[x]+1;q.push(v);}}}}int augment(){int a=INF;for(int u=t;u!=s;u=edges[p[u]].fr){Edge &e=edges[p[u]];a=min(a,e.cap-e.fw);}for(int u=t;u!=s;u=edges[p[u]].fr){edges[p[u]].fw+=a;edges[p[u]^1].fw-=a;}return a;}int maxFlow(int s,int t){this->s=s,this->t=t;bfs(t);int flow=0;memset(gap,0,sizeof(gap));for(int i=0;i<n;++i) ++gap[d[i]];memset(cur,0,sizeof(cur));int x=s;while(d[s]<n){if(x==t){flow+=augment();x=s;}int flag=false;for(int i=cur[x];i<G[x].size();++i){Edge &e=edges[G[x][i]];if(e.cap>e.fw&&d[x]==d[e.to]+1){flag=true;p[e.to]=G[x][i];cur[x]=i;x=e.to;break;}}if(!flag){int m=n-1;for(int i=0;i<G[x].size();++i){Edge &e=edges[G[x][i]];if(e.cap>e.fw) m=min(m,d[e.to]);}if((--gap[d[x]])==0) break;d[x]=m+1;++gap[d[x]];cur[x]=0;if(x!=s) x=edges[p[x]].fr;}}return flow;}
};
ISAP solver;int d,f,b;
int dd[4][2]={{-1,0},{1,0},{0,-1},{0,1}};bool ok(int x,int y)
{return x>=1&&x<=n&&y>=1&&y<=m;
}int main()
{int T;scanf("%d",&T);while(T--){int cnt=0;scanf("%d%d",&m,&n);scanf("%d%d%d",&d,&f,&b);for(int i=1;i<=n;++i){scanf("%s",p[i]+1);if(p[i][1]=='.'){++cnt;p[i][1]='#';}if(m>1&&p[i][m]=='.'){++cnt;p[i][m]='#';}if(i==1||i==n)for(int j=1;j<=m;++j)if(p[i][j]=='.'){++cnt;p[i][j]='#';}}solver.init(n*m+2);for(int i=1;i<=n;++i){for(int j=1;j<=m;++j){for(int k=0;k<4;++k){int ni=i+dd[k][0],nj=j+dd[k][1];if(ok(ni,nj)) solver.addEdge((i-1)*m+j,(ni-1)*m+nj,b);}if(p[i][j]=='#'){if(i==1||i==n||j==1||j==m)solver.addEdge(0,(i-1)*m+j,INF);elsesolver.addEdge(0,(i-1)*m+j,d);}else{solver.addEdge((i-1)*m+j,n*m+1,f);}}}printf("%d\n",solver.maxFlow(0,n*m+1)+cnt*f);}return 0;
}

  

转载于:https://www.cnblogs.com/20143605--pcx/p/5107954.html

UVA-1515 Pool construction (最小割)相关推荐

  1. UVA 1515 - Pool construction(最小割)

    题目链接 https://cn.vjudge.net/problem/UVA-1515 [题意] 输入一个h行w列的字符矩阵,草地用'#'表示,洞用'.'表示,可以把一个草地换成洞,费用为d,也可以把 ...

  2. UVA - 10480 Sabotage 输出最小割方案

    题目链接 https://vjudge.net/problem/UVA-10480 题意 无向图求最小割的方案 思路 最小割部分是模版,问题在于最小割的方案如何输出. 首先根据最小割最大流定理,我们跑 ...

  3. Pool construction UVA - 1515 最小割模型

    传送门 文章目录 题意: 思路: 题意: 给你一个n∗mn*mn∗m的矩阵,包含字符#和.,将#变成.的代价是ddd,将.变成#的代价是fff,让后将#和.隔开的代价是bbb,现在让你用最小的代价将# ...

  4. UVA - 10480 Sabotage 最小割,输出割法

    UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解: ...

  5. UVA - 10480 Sabotage(最小割-最大流+输出割边)

    题目链接:点击查看 题目大意:给出一张无向图,1为起点,2为终点,删除每条边都需要权值wi,题目需要求将起点与终点分割为两个部分的最小花费,并且输出方案 题目分析:如果不让输出方案的话就是一个裸的最大 ...

  6. Sabotage UVA - 10480 (最小割+求最小割去掉的具体边+ISAP)

    传送门 题意:给定n个点,m条带权无向边,源点s=1,汇点t=2.去掉一些边之后使s,t不连通,求去掉的这些边(而且还要满足去掉的边权和是所有答案中最小的--最小割). n<=50,m<= ...

  7. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  8. [学习笔记]最小割之最小点权覆盖最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  9. POJ 1966 Cable TV Network【无向图点连通度 最小割 E-K算法求最大流】

    题目描述: 给你一个无向图,问你最少删掉几个点,使这个图成不连通. 解题报告: 概念 (1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通, ...

最新文章

  1. ant 获取当前url的参数
  2. 分布式概念-中心化副本控制机制
  3. CV绿色的上限和下限
  4. 深度 | 人工智能的游戏征途:超级玛丽简直小菜一碟,星际争霸、LOL才是大boss...
  5. PHP将死。何以为继?
  6. 【Python面试】 说说Python面向对象三大特性?
  7. PHP openssl加密扩展使用总结
  8. 题目:有一分数序列:2 / 1,3 / 2,5 / 3,8 / 5,13 / 8,21 / 13...求出这个数列的前20项之和。
  9. 什么工作经常出差_职场妈妈困扰: 经常出差, 工作孩子该怎么选择?
  10. DigWS 短消息和WapPush 快速开发指南-功能介绍
  11. 圆通电子面单接口对接
  12. 怎么进入计算机网络权限设置方法,电脑怎么设置网络访问权限保护共享文件安全...
  13. MP4文件格式的相关内容
  14. android xml画圆,Android自定义View画圆功能
  15. Oulipo HDU - 1686 (使用扩展kmp进行讨伐!)
  16. 手机上能搭建mysql服务器_安卓手机搭建网站服务器【Php+Mysql+Lighttpd】 – 楚盟博客...
  17. Word2016 显示批注
  18. 易基因 - 学科前沿:转录组测序在原核致病菌中的研究应用(1)|文献科普
  19. 最冷招聘季:裁员后,我求职沟通1398次,投277份简历,面试72场
  20. 计算机教学反思杂文,政治教学反思教学随笔

热门文章

  1. Spring Boot静态资源访问和配置全解析
  2. 电路基础知识 -- 三态
  3. ifstream 和 ofstream 文件中读取和写入操作
  4. 分布式入门,怎样用PyTorch实现多GPU分布式训练
  5. 如何设计区块链项目的通证(token)模型
  6. Android 插件化原理解析——Service的插件化
  7. 【问链-EOS公开课】第八课 EOS 数据库与持久化 API(一)
  8. 双代号网络图基础算法_9个简单数学算法在管理领域的运用
  9. AtCoder AGC019E Shuffle and Swap (DP、FFT、多项式求逆、多项式快速幂)
  10. BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演)