博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 4261: 建设游乐场 费用流
阅读量:5102 次
发布时间:2019-06-13

本文共 4380 字,大约阅读时间需要 14 分钟。

题目

现在有一大块土地,可以看成N*M的方格。在这块土地上,有些格子内是崎岖的山地,无法建造任何东西;其他格子都是平原。现在打算在这块土地上建设一个游乐园。游乐园由若干条闭合的过山车轨道组成,每个平原格子都要铺一截轨道,为下列 6 种类型中的一种:

1055088-20170518101427291-1240258904.bmp
(每张图表示一块平原格子,图内网格线为辅助线,无实际意义。)
其中前 2 种为直轨道,后 4 种为弯轨道。显然对游客来说,弯轨道更加刺激。
由于每块格子风景各不相同,经过一番研究,现给了N*M个方格中的每个格子一个评估值,意义为:如果该格子修建弯轨道,会给游客们带来多少的愉悦值。现需要一名设计师,帮他设计一种最优的轨道建设方案,使所有格子给游客们带来的愉悦值之和尽量大。(如果没有合法方案,输出 -1)
N<=150,M<=30,Vi,j<=100

题解:

乍一看没有什么思路.

但仔细观察一下可以通过直觉感觉出来是网络流。
(OI人的直觉)
在棋盘问题上应用网络流算法,经典的就是黑白染色。
所以我们将棋盘黑白染色。
然后我们考虑怎样构造方案:

  • 一定有每个黑色格子与两个白色格子连接且每个白色格子与两个黑色各自连接.
    如果能达到这个,那么一定可行.
    所以可以用最大流来判断是否可行.

1055088-20170518101351822-1946075133.png

其中每个加粗边的流量是2,然后我们判断一下最大流是否为节点数即可.

那么对于转弯时付出的代价要怎么计算?
我们还是在上述的模型中进行改进,我们对边赋以权值。
然后考虑把点拆成和x方向的白点进行连接与和y方向的白点进行连接两种点。
然后再加一个点来控制到达这两个点的总流量为2。
然后就很明朗了,我们只要完成这么一个限制:如果流量分别走了两边,就获得权值。

... ...

但是经过仔细思考后并不能完成这么一个限制...

所以考虑转化一下。我们知道上述条件等价于:如果流量都走了同一边,就无法获得权值.
这个限制是我们可以简单完成的,只要利用凸费用流的性质即可.
所以跑最小费用最大流即可.

#include 
#include
#include
using namespace std;typedef long long ll;inline void read(int &x){ x=0;char ch;bool flag = false; while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true; while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;}#define rg register int#define rep(i,a,b) for(rg i=(a);i<=(b);++i)#define per(i,a,b) for(rg i=(a);i>=(b);--i)const int maxn = 160;const int maxm = 36;const int maxnode = 3*maxn*maxm;const int maxedge = maxnode*4;struct Edge{ int to,next,cost,cap;}G[maxedge<<1];int head[maxnode],cnt = 1;inline void add(int u,int v,int c,int d){ G[++cnt].to = v; G[cnt].next = head[u]; G[cnt].cap = c; G[cnt].cost = d; head[u] = cnt;}inline void insert(int u,int v,int c,int d){ add(u,v,c,d);add(v,u,0,-d);}#define v G[i].toconst int lim = maxnode<<1;int q[lim+10],dis[maxnode],p[maxnode];int flow[maxnode];int l,r,S,T,fl;ll ans;bool inq[maxnode];int nodecnt;const int inf = 0x3f3f3f3f;inline bool spfa(){ rep(i,1,nodecnt){ dis[i] = inf; inq[i] = false; } l = 0;r = -1;q[++r % lim] = S; inq[S] = true;flow[S] = inf; dis[S] = 0; while(l <= r){ int u = q[l++ % lim]; for(rg i = head[u];i;i=G[i].next){ if(dis[v] > dis[u] + G[i].cost && G[i].cap > 0){ dis[v] = dis[u] + G[i].cost; flow[v] = min(flow[u],G[i].cap); p[v] = i; if(!inq[v]){ q[++r % lim] = v; inq[v] = true; } } }inq[u] = false; }if(dis[T] == inf) return false; ans += 1LL*flow[T]*dis[T]; fl += flow[T]; for(rg u = T;u != S;u = G[p[u]^1].to) G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T]; return true;}#undef vint idx[maxn][maxm],idy[maxn][maxm],id[maxn][maxm];int main(){ int n,m;read(n);read(m); int x,num = 0; rep(i,1,n){ rep(j,1,m){ read(x); if(x == 0){ ++ num; id[i][j] = ++ nodecnt; idx[i][j] = ++ nodecnt; idy[i][j] = ++ nodecnt; } } } ll tot = 0; S = ++ nodecnt;T = ++ nodecnt; rep(i,1,n){ rep(j,1,m){ read(x); if(id[i][j] == 0) continue; tot += x; if((i+j)&1^1){ insert(S,id[i][j],2,0); insert(id[i][j],idx[i][j],1,0); insert(id[i][j],idx[i][j],1,x); insert(id[i][j],idy[i][j],1,0); insert(id[i][j],idy[i][j],1,x); }else{ insert(id[i][j],T,2,0); insert(idx[i][j],id[i][j],1,0); insert(idx[i][j],id[i][j],1,x); insert(idy[i][j],id[i][j],1,0); insert(idy[i][j],id[i][j],1,x); } if((i+j)&1^1){ int x,y; x = i-1;y = j; if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idx[i][j],idx[x][y],1,0); x = i+1;y = j; if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idx[i][j],idx[x][y],1,0); x = i;y = j-1; if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idy[i][j],idy[x][y],1,0); x = i;y = j+1; if(1<=x && x<=n && 1<=y && y<=m && id[x][y]) insert(idy[i][j],idy[x][y],1,0); } } } while(spfa()); if(fl != nodecnt / 3){ puts("-1"); return 0; } printf("%lld\n",tot - ans); return 0;}

转载于:https://www.cnblogs.com/Skyminer/p/6871963.html

你可能感兴趣的文章
Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3
查看>>
第23月第24天 git命令 .git-credentials git rm --cached git stash clear
查看>>
java SE :标准输入/输出
查看>>
一些方便系统诊断的bash函数
查看>>
<转>关于MFC的多线程类 CSemaphore,CMutex,CCriticalSection,CEvent
查看>>
jquery中ajax返回值无法传递到上层函数
查看>>
css3之transform-origin
查看>>
[转]JavaScript快速检测浏览器对CSS3特性的支持
查看>>
Master选举原理
查看>>
[ JAVA编程 ] double类型计算精度丢失问题及解决方法
查看>>
小别离
查看>>
微信小程序-发起 HTTPS 请求
查看>>
WPF动画设置1(转)
查看>>
基于node/mongo的App Docker化测试环境搭建
查看>>
java web 中base64传输的坑
查看>>
java 中的线程(一)
查看>>
秒杀9种排序算法(JavaScript版)
查看>>
Activiti入门 -- 环境搭建和核心API简介
查看>>
struts.convention.classes.reload配置为true,tomcat启动报错
查看>>
MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)
查看>>