1515 - Pool construction
2015-08-17 13:16
295 查看
我有话说:
在这道题里,首先我们根据题目可以想到的是要预先算出把边界的洞填上草所需要的花费,同时在图中修改。然后就是要考虑内部的情况。所有的点都是草或者洞,栅栏是把草和洞隔开的作用,就对应上图论中“割”的概念。我们可以把所有的草连上同一个源点s,所有的洞连上同一个汇点t。从s到草的边我们记其容量为d的边,即对应只有把这条边切断,这个点才会属于“洞”这一集合,即和t相连。然后根据在图中的每一个点和他周围的点之间连上容量为b的边(栅栏),然后求这个图的最大流最小割即可。用的是Dinic算法。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <queue> using namespace std; const int maxn=50*50+10; const int INF=10000000000; struct Edge{ int from,to,cap,flow; }; bool operator < (const Edge& a,const Edge& b) { return a.from<b.from||(a.from==b.from&&a.to<b.to); } struct Dinic { int n,m,s,t; vector<Edge>edges; vector<int>G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; void init(int n){ for(int i=0;i<n;i++)G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap){ edges.push_back((Edge){from,to,cap,0}); edges.push_back((Edge){to,from,0,0}); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS(){ memset(vis,0,sizeof(vis)); queue<int>Q; Q.push(s); vis[s]=1; d[s]=0; 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(!vis[e.to]&&e.cap>e.flow){ d[e.to]=d[x]+1; vis[e.to]=1; Q.push(e.to); } } } return vis[t]; } int DFS(int x,int a){ if(x==t||a==0)return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++){ Edge& e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; } int MaxFlow(int s,int t){ this->s=s;this->t=t; int flow=0; while(BFS()){ memset(cur,0,sizeof(cur)); flow+=DFS(s,INF); } return flow; } }; int w,h; char pool[99][99]; inline int ID(int i,int j){ return i*w+j; } Dinic g; int main() { int T,d,f,b; cin>>T; while(T--){ scanf("%d%d%d%d%d",&w,&h,&d,&f,&b); for(int i=0;i<h;i++){ scanf("%s",pool[i]); } int cost=0; for(int i=0;i<w;i++){ if(pool[0][i]=='.'){pool[0][i]='#';cost+=f;} if(pool[h-1][i]=='.'){pool[h-1][i]='#';cost+=f;} } for(int i=0;i<h;i++){ if(pool[i][0]=='.'){pool[i][0]='#';cost+=f;} if(pool[i][w-1]=='.'){pool[i][w-1]='#';cost+=f;} } g.init(w*h+2); for(int i=0;i<h;i++){ for(int j=0;j<w;j++){ if(pool[i][j]=='#'){ int cap=INF; if(i!=0&&i!=h-1&&j!=0&&j!=w-1)cap=d; g.AddEdge(h*w,ID(i,j),cap); }else{ g.AddEdge(ID(i,j),h*w+1,f); } if(i>0)g.AddEdge(ID(i,j),ID(i-1,j),b); if(i<h-1)g.AddEdge(ID(i,j),ID(i+1,j),b); if(j>0)g.AddEdge(ID(i,j),ID(i,j-1),b); if(j<w-1)g.AddEdge(ID(i,j),ID(i,j+1),b); } } printf("%d\n",cost+g.MaxFlow(h*w,h*w+1)); } return 0; }
相关文章推荐
- JNI 可变印刷
- 程序内存管理
- 如何在 MIT Scheme 中运行 Scheme 语言程序
- 解决PHP执行乱码、每次都要手动更改Firefox Unicode设置问题
- poj 3080 Blue Jeans 暴力
- 如何获得运行在跨平台的信息和属性的情况下,文件
- 读取文件夹以及消除
- iOS 模糊、精确搜索匹配功能方法总结 By HL
- 艺术品收集
- 【攻克Android (33)】四大组件之 BroadcastReceiver
- Java虚拟机详解----常用JVM配置参数
- 不同噪声下滤波器的选择
- MongoDB 聚合
- MongoDB 备份
- RelativeLayout
- MongoDB分页、排序与游标
- MongoDB索引
- jquery过滤器之:contains()、.filter()
- unity上面调用andorid相册的插件-android部分
- linux 生名变量类型 declare