题目大意:有一块地,分成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. rpm 安装 忽略依赖_解决RPM包依赖关系
  2. 完全解读ping命令应用方法
  3. 计算机与人脑_看!自行车成精了...清华网红自行车:拥有“类人脑芯片”,可无人驾驶...
  4. 2017年热度最高的十大技术类技能
  5. Qt QML实现阴影字体
  6. C#中打开设计视图时报未将对象引用设置到对象的实例
  7. RFC函数的初步使用-同步
  8. 推荐算法--推荐系统架构(06)
  9. SAP License:瞎搞!你真的懂什么是ERP、中台和低代码吗?
  10. vuex辅助函数和vuex5个属性
  11. System.Data.SqlClient.SqlError: 尚未备份数据库的日志尾部
  12. 百度cdn几时能入币_影响汇率的因素有哪些
  13. ARM+DSP双核处理器应用程序攻略
  14. 音视频开发之旅(六) -----Android集成webrtc降噪和增益模块, ns_core函数简析
  15. 【Pranet】论文及代码解读(ResNet部分)——jialiang nie
  16. ppt中插入和删除动画
  17. 百度网盘提速正规办法 无需破解!!!!!
  18. 将qlv类型的视频转换mp4格式的最新做法
  19. 吴军《数学之美》部分概念笔记(1-11章)
  20. 广域网协议(HDLC协议和PPP协议)

热门文章

  1. Typora + PicGo + Gitee
  2. 【C/C++多线程编程之八】pthread条件变量
  3. STM32开发 -- 主天线和分集天线
  4. 逆元~(乘法逆元及其应用)
  5. zcmu-1931(dfs方格切割)
  6. stl-unique()函数去重
  7. android6.0源码分析之Camera2 HAL分析
  8. Android Bitmap面面观
  9. 合作模式歌利亚机器人_智能时代挑战下的机器人教育新方向!
  10. python中赋值不正确的_python中关于赋值、浅拷贝与深拷贝的问题