uva 1515 Pool construction(最小割)
来源:互联网 发布:linux daemon命令 编辑:程序博客网 时间:2024/05/29 18:22
题目大意:给一块n×m的地皮,上面有草地‘#’和洞‘.’ 。草地转换成洞需要d的费用,把洞填上种上草需要f的费用,在草地和洞之间加一道墙需要b的费用。现在问把这块n×m的地皮变成池子的最小费用是多少。(池子:边缘必须都是草地,每块草地与洞之间都有墙隔开)
解题思路:建图方式非常巧妙。先把所有边界上的洞全部变成草地,并记录费用sum。设置超级源点,连向所有边界的草地,容量为INF,然后连向其他草地,容量为d。设置超级汇点,使所有的洞,连向超级汇点,容量为f。然后地皮内每个点都与相邻的点连边,容量为b。
#######.###.#.######
超级源点向(3,3)的#连了一条边,容量为d。如果将d转换为洞的话最终答案ans + 3b - (d + b)。所以要不要对(3,3)进行转换,就变成了3b和(d + b)也就是d 和2b谁大谁小的问题。当d大于2b时,把#转换成洞是不划算的,在最大流中体现为,当d >= 2b时,(3,3)点接受了(4,3)点流入的流,(3,3)点的流量就会化为三段b的流流向(2,3)(3,2)(3,4)三个点(最大流嘛,三条边满流),就相当于在不转化(3,3)点,并在其与(2,3)(3,2)(3,4)三个点间建墙,流量 = 费用 = 3b。当d < 2b时,即使接受了(4,3)点流入的流,(3,3)点的流量还是不够流满(2,3)(3,2)(3,4)三个点,所以最后流向三个点的流量并没有3b,而是本身流量加上(4,3)点流入的流量,流量 = 费用 = d + b,也就是把(3,3)点转换为洞啦。
题解转自:http://blog.csdn.net/llx523113241/article/details/48195599
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cctype>#include <cstdlib>#include <cmath>#include <string>#include <map>#include <set>#include <queue>#include <vector>#include <stack>#include <cctype>using namespace std;typedef unsigned long long ULL;const int maxn = 3000;const int INF = 0x3f3f3f3f;bool used[maxn];int n,m;///n行struct edge{ int to,cap,rev;};vector <edge> G[maxn];void addedge(int from,int to,int cap){ G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1});}int dfs(int v,int t,int f){ if(v==t) return f; used[v] = 1; for(int i =0;i<G[v].size();++i){ edge &e = G[v][i]; if(!used[e.to] &&e.cap>0){ int d = dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0;}int max_flow(int s,int t){ int flow = 0; while(1){ memset( used,0,sizeof(used)); int f = dfs(s,t,INF); if(f==0) break; flow += f; } return flow;}int ans = 0,S,T;int d,f,b;int id[maxn][maxn];///节点编号char g[maxn][maxn];///原图int dx[4] = {0,0,1,-1};int dy[4] = {-1,1,0,0};void init(){ for(int i = 0;i<maxn;++i){ G[i].clear(); } ans = 0;}///起点为0 终点为n*m+1void changenum(){ S = 0; T = m*n+1; for(int i = 0;i < n;++i){ for(int j = 0;j < m;++j){ id[i][j] = i*m+j+1; } }}int main() { int t;scanf("%d",&t);for(int tt = 1; tt<=t;++tt){ init(); scanf("%d%d%d%d%d",&m,&n,&d,&f,&b);///m列,变洞d,变草f,围栏b for(int i = 0;i < n;++i){ scanf("%s",g[i]); } changenum(); for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ if(j == 0 || j == m-1 || i == 0 || i == n-1){ if(g[i][j] == '.') ans += f; addedge(S,id[i][j],INF);///起点向草连边 } else{ if(g[i][j] == '.') addedge(id[i][j],T,f);///洞向终点连边 else addedge(S,id[i][j],d);///起点向草连边 } ///四个方向互相连边 for(int k = 0; k < 4; ++k){ int ni = i+dx[k],nj = j+dy[k]; if(ni<0 || ni>=n || nj<0 || nj>=m) continue; addedge(id[i][j],id[ni][nj],b); } } } printf("%d\n",ans+max_flow(S,T));} return 0;}/*33 35 5 1#.##.####5 41 8 1#..####.###.#.######2 227 11 11#..#*/
1 0
- UVA 1515 Pool construction(最小割)
- uva 1515 Pool construction(最小割)
- 最小割 UVA 1515 Pool construction
- UVA 1515 Pool construction [最小割]
- 1515 - Pool construction(最大流最小割模型)
- [最小割最大流]UVa1515 - Pool construction
- Uva-1515-Pool construction
- UVa 1515 Pool construction
- UVA 1515 Pool construction
- UVA 1515Pool construction
- UVA 1515 Pool construction
- uva 1515 Pool construction(最大流)
- UVA 1515 Pool construction(网络流)
- UVA 1515 (最小割)
- 1515 - Pool construction
- 最大流,最小割(水塘,uva 1515)
- UVa 1515 简单最小割模型
- UVA 1212 - Duopoly(最小割)
- Android实现水波纹效果波纹效果(Ripple)
- C++实验6-矩阵求和
- 十天训练营结业作业
- Raknet 库学习一
- 单例模式加锁与不加锁实例C++
- uva 1515 Pool construction(最小割)
- 基于opencv2加载一张图片,画方框,以及删除图片原文件
- Linux date命令
- Linux_ALSA声卡驱动原理分析
- Hibernate:关于Column '*' not found和could not deserialize
- arcgis 复制图层内的数据不成功
- React 学习解疑
- Calendar类
- Microsoft Bot Framework with LUIS