UVALive 5905 Pool Construction 最小割,s-t割性质 难度:3
2015-03-18 22:23
411 查看
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3916
这道题要求一种填充+挖坑+建屏障的方法,使得这块土地上的所有坑和草地之间都有屏障,挖坑花费d每块,填充花费f每块,建屏障花费b每两块之间,注意并不要求一定有坑,但是外围一圈要一定没有坑,所以需要预先填充好
令st代表平地,ed代表坑,边权为花费,那么本题是要求一个st-ed最小割,因为s到平地花费为0,所以不建边,同理坑到ed也不需要花费不建边,每个点到相邻点建边,容量为b,s到坑建边,容量为d,平地到e建边,容量为f,为了防止外围的平地被挖,容量设为inf.
以st为起点,ed为终点,求一遍最大流,即最小割即可
这道题一开始会以为是dp,其实是一道最小割,虽然有2500个点,50000条边左右,但是仍然可以用网络流跑过,一开始想不出怎么处理屏障,但是其实只需要把每个点和相邻点之间都连起来即可,横向的流量没有意义,也就是说只有平地和坑之间的边会限制流量.
这道题要求一种填充+挖坑+建屏障的方法,使得这块土地上的所有坑和草地之间都有屏障,挖坑花费d每块,填充花费f每块,建屏障花费b每两块之间,注意并不要求一定有坑,但是外围一圈要一定没有坑,所以需要预先填充好
令st代表平地,ed代表坑,边权为花费,那么本题是要求一个st-ed最小割,因为s到平地花费为0,所以不建边,同理坑到ed也不需要花费不建边,每个点到相邻点建边,容量为b,s到坑建边,容量为d,平地到e建边,容量为f,为了防止外围的平地被挖,容量设为inf.
以st为起点,ed为终点,求一遍最大流,即最小割即可
这道题一开始会以为是dp,其实是一道最小割,虽然有2500个点,50000条边左右,但是仍然可以用网络流跑过,一开始想不出怎么处理屏障,但是其实只需要把每个点和相邻点之间都连起来即可,横向的流量没有意义,也就是说只有平地和坑之间的边会限制流量.
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=5000; const int maxm=5000000; const int inf=0x3fffffff; int first[maxn]; struct edge{ int nxt,from,t,f,c; }e[maxm]; int w,h,d,fl,b,len; char maz[60][60]; const int dx[4]={1,-1,0,0}; const int dy[4]={0,0,1,-1}; int st,ed,num; int dis[maxn],gap[maxn]; bool in(int x,int y){return x>=0&&x<h&&y>=0&&y<w;} void addedge(int from,int t,int c){ e[len].nxt=first[from]; e[len].from=from; e[len].t=t; e[len].f=c; e[len].c=c; first[from]=len++; swap(from,t);c=0; e[len].nxt=first[from]; e[len].from=from; e[len].t=t; e[len].f=c; e[len].c=c; first[from]=len++; } int dfs(int s,int flow){ if(s==ed)return flow; int mindis=num-1; int tflow=flow,sub; for(int p=first[s];p!=-1;p=e[p].nxt){ int t=e[p].t; if(e[p].f>0){ if(dis[t]+1==dis[s]){ sub=dfs(t,min(tflow,e[p].f)); e[p].f-=sub;e[p^1].f+=sub; tflow-=sub; if(dis[st]>=ed)return flow-tflow; if(tflow<=0)break; } mindis=min(mindis,dis[t]); } } if(flow-tflow<=0){ --gap[dis[s]]; if(gap[dis[s]]==0)dis[st]=ed; else { dis[s]=mindis+1; ++gap[dis[s]]; } } return flow-tflow; } int maxflow(){ int flow=0; gap[0]=num; while(dis[st]<ed){ flow+=dfs(st,inf); } return flow; } void init(){ len=0; st=w*h; ed=st+1; num=st+2; fill(first,first+num,-1); fill(gap,gap+num,0); fill(dis,dis+num,0); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d",&w,&h,&d,&fl,&b); init(); int ans=0; for(int i=0;i<h;i++)scanf("%s",maz[i]); for(int i=0;i<h;i++){ for(int j=0;j<w;j++){ for(int k=0;k<4;k++){ int tx=i+dx[k],ty=j+dy[k]; if(in(tx,ty)){ addedge(i*w+j,tx*w+ty,b); } } if(maz[i][j]=='#'){ if(i==0||i==h-1||j==0||j==w-1){ addedge(i*w+j,ed,inf); } else { addedge(i*w+j,ed,d); } } else { if(i==0||i==h-1||j==0||j==w-1){ ans+=fl; maz[i][j]='#'; addedge(i*w+j,ed,inf); } else { addedge(st,i*w+j,fl); } } } } ans+=maxflow(); printf("%d\n",ans); } return 0; }
相关文章推荐
- 【UVALive - 3487】 Duopoly(网络流-最小割)
- 【UVALive】3661 Animal Run 平面图最小割 最短路
- UVALive 3971-Assemble- 最小值最大化(二分)
- UVALIVE 3661 Animal Run <最大-最小原理之一 最大流-最小割原理>
- UVALive 6837 (最小生成树)
- CF 160D Edges in MST 最小生成树的性质,寻桥,缩点,批量处理 难度:3
- UVALive 5059 Play with Stones SG函数,难度较低
- Kejin Game UVALive - 7264 拆点+最小割 15北京区域赛
- UVALive 2755 Hidden Password (最小表示法)
- UVALive 4872 Underground Cables 最小生成树
- Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配
- UVALive 6437 Power Plant 【最小生成树 + 思维】
- [UVALive] 6492 Welcome Party(最小点覆盖)
- UVALive-7303- Aquarium【最小生成树】【连通块】
- UVALive 5099 Nubulsa Expo 全局最小割 非网络流 n^3
- Another Minimum Spanning Tree - UVaLive 3662 曼哈顿最小生成树
- uvalive4840(n*n方阵的最小花费)
- UVALive 5903 Piece it together 二分匹配,拆点 难度:1
- Delivering Goods UVALive - 7986(最短路+最小路径覆盖)
- C - Underwater Snipers UVALive - 5000 最小值最大化问题 二分