【思维题 费用流 技巧】bzoj5403: marshland
主要还是网络流拆点建图一类技巧吧
Description
第一眼看到这题时候只会把每个点拆成4个方向;再强制定向连边防止成环;最后做一遍最大费用可行流。
然而这种做法显然比较复杂,且关于强制定向我也并不是很熟练……
再仔细研究一下题目的性质,发现危险度所处的格子奇偶性是相同的。这种性质使得我们可以以黑白染色的角度考虑强制定向的问题。
设$X+Y$为奇数的点为黑点;为偶数的点为白点。那么“折形”的限制就表述为每当选了一个黑点,就在上下、左右各选一个白点相连。对于费用流的建模,我们可以看做黑点放在中间,上下的白点在左边连向黑点;左右的白点在右边与黑点相连。首先来看中间的黑点,为了从费用流角度表示选取黑点,当然就是拆点连费用为$v[i][j]$的边。再是黑点两侧的点,需要注意的有:一、此处只是表示出了全图的一个部分,这里的白点还会和其他黑点产生关系,因此“两侧”的白点区别应当从所属行的奇偶性考虑。二、既然已经对黑点强制定向,那么“两侧”的白点就当分类分别处理与$S,T$的连边。
从这个角度建模后,由于对于每一个黑点都有关于相邻白点的$S,T$通路,那么每增广一次必然是在最大流的前提下保证选了当前最大费用。之所以提这一点,是因为有一些不恰当的建图方式把以S为起点的拓扑序安排得很混乱,以至于各个危险点之间的选取并不是完全分离的过程。
那么,剩下的就是一遍最大费用可行流的事情了。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = ;
const int maxNode = ;
const int maxm = ;
const int INF = 2e9; struct Edge
{
int u,v,f,c,cst;
Edge(int a=, int b=, int c=, int d=, int e=):u(a),v(b),f(c),c(d),cst(e) {}
}edges[maxm];
int n,lim,k,S,T;
int id[maxn][maxn],v[maxn][maxn];
int edgeTot,head[maxNode],nxt[maxm],bck[maxNode],flw[maxNode];
ll ans,cst[maxNode];
bool inq[maxNode],chk; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v, int c, int cst)
{
edges[edgeTot] = Edge(u, v, , c, cst), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
edges[edgeTot] = Edge(v, u, , , -cst), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
}
void maxFlow()
{
std::queue<int> q;
memset(bck, , sizeof bck);
memset(flw, , sizeof flw);
memset(cst, -0x3f3f3f3f, sizeof cst);
q.push(S), flw[S] = INF, cst[S] = ;
for (int tmp; q.size(); )
{
tmp = q.front(), q.pop(), inq[tmp] = ;
for (int i=head[tmp]; i!=-; i=nxt[i])
{
int v = edges[i].v;
if (cst[tmp]+edges[i].cst > cst[v]&&edges[i].f < edges[i].c){
cst[v] = cst[tmp]+edges[i].cst, bck[v] = i;
flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
if (!inq[v]) inq[v] = , q.push(v);
}
}
}
if (cst[T] < ) chk = false;
else{
for (int i=T; i!=S; i=edges[bck[i]].u)
edges[bck[i]].f += flw[T], edges[bck[i]^].f -= flw[T];
ans -= cst[T]*flw[T];
}
}
int main()
{
memset(head, -, sizeof head);
n = read(), lim = read(), k = read();
S = , T = n*n*+;
for (int i=, cnt=; i<=n; i++)
for (int j=; j<=n; j++)
id[i][j] = ++cnt, v[i][j] = read(), ans += v[i][j];
for (; k; --k) v[read()][read()] = INF;
for (int i=; i<=n; i++)
for (int j=; j<=n; j++)
if (v[i][j]!=INF){
if ((i+j)&) addedge(id[i][j], id[i][j]+n*n, , v[i][j]);
else{
if (i&){
addedge(S, id[i][j], , );
if (i > ) addedge(id[i][j], id[i-][j], , );
if (i < n) addedge(id[i][j], id[i+][j], , );
if (j > ) addedge(id[i][j], id[i][j-], , );
if (j < n) addedge(id[i][j], id[i][j+], , );
}else{
addedge(id[i][j], T, , );
if (i > ) addedge(id[i-][j]+n*n, id[i][j], , );
if (i < n) addedge(id[i+][j]+n*n, id[i][j], , );
if (j > ) addedge(id[i][j-]+n*n, id[i][j], , );
if (j < n) addedge(id[i][j+]+n*n, id[i][j], , );
}
}
}
chk = true;
for (; lim&&chk; --lim) maxFlow();
printf("%lld\n",ans);
return ;
}
END
【思维题 费用流 技巧】bzoj5403: marshland的更多相关文章
- hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
题意: 一个数字矩阵,可以出发K次,每次可以从右边或者下面走,要求(在收益最大情况下)覆盖全图,不能则输出-1.(规则:每次跳一步的时候若格子数字相等则获得该数字的能量,每跳一步消耗距离的能量).每个 ...
- CFGYM 2013-2014 CT S01E03 D题 费用流模版题
题意: n行, a房间的气球,b房间的气球 i行需要的气球,与a房的距离,b房的距离 求最小距离 #include <stdio.h> #include <string.h> ...
- [费用流][BZOJ1070]修车
修车 题目描述 同一时刻有位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均 ...
- 【Luogu】P2488工作安排(费用流)
题目链接 这题……费用流即可……(哇啊要被打死辣) 然而我printf("%d")爆零四次 好的心如死灰 #include<cstdio> #include<cs ...
- [bzoj 1449] 球队收益(费用流)
[bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...
- 【Tyvj1982】武器分配(费用流)
题意:有N个人要从A个物品中各取一个,B个物品中各取一个,选取第i个A类物品和第j个B类物品的费用是(a[i]-b[j])^2 求最小总花费 n<=a,b<=80 a[i],b[i]< ...
- 【网络流24题】No.19 负载平衡问题 (费用流)
[题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input ...
- 【费用流】BZOJ1061: [Noi2008]志愿者招募(这题超好)
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5291 Solved: 3173[Submit][Stat ...
- 【zkw费用流】[网络流24题]餐巾计划问题
题目描述 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分(f ...
随机推荐
- DOM事件-冒泡、捕获、传播、委托
事件捕获 以点击事件为例事,同类型事件会由根元素开始触发,向内传播,一直到目标元素.从外到内依次触发:根—目标的祖先素—目标的父元素—目标元素. 事件冒泡 根事件捕获截然相反.发生点击事件时,事件会从 ...
- Corn Fields(模板)
题目链接 #include <stdio.h> #include <algorithm> #include <string.h> #include <iost ...
- mysql5.7日志时间戳(log_timestmaps)与系统时间不一致问题以及日志报Got an error reading communication packets情况分析
一.mysql安装后error_log日志时间戳默认为UTC(如下图),因此会造成与系统时间不一致,与北京时间相差8个小时. 解决errro_logs时间戳与linux系统时间不一致问题 step1: ...
- Linux —— ps命令
Ps命令 作用 显示瞬间进程的状态,并不动态连续: 如果想对进程进行实时监控应该用top命令: 对进程的管理,可以使用kill命令发送信号 Ps PID : 运行着的命令的进程编号 TTY : 命令所 ...
- JavaScript读取文本,并渲染在html
html <pre id="myText" style="word-wrap: break-word; white-space: pre-wrap; white-s ...
- NET Core+MySql+Nginx
NET Core+MySql+Nginx 容器化部署 .NET Core容器化@Docker.NET Core容器化之多容器应用部署@Docker-Compose.NET Core+MySql+Ngi ...
- python 8 函数
调用函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数.可以直接从Python的官方网站查看文档: 也可以在交 ...
- Linux用脚本守护进程
while true; do server=`ps -aux | grep tomcat | grep -v grep` if [ ! "$server" ]; then echo ...
- springboot集成shiro实现权限认证
github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...
- Flash图表控件FusionCharts如何高亮显示数据
使用Flash图表控件FusionCharts时,通过改变alpha值是高亮显示数据的最简单方式. XML代码如下: <chart> <set label='John' value= ...