题面:

Description
Nick最近在玩一款很好玩的游戏,游戏规则是这样的:
有一个n*m的地图,地图上的每一个位置要么是空地,要么是炮塔,要么是一些BETA狗,Nick需
要操纵炮塔攻击BETA狗们。
攻击方法是:对于每个炮塔,游戏系统已经给出它可以瞄准的方向(上下左右其中一个),Nick需要
选择它的攻击位置,每一个炮塔只能够攻击一个位置,炮塔只能够向着它的瞄准方向上的某个位置发
动攻击,当然炮塔也可以不进行攻击。炮塔威力强大,它可以且仅可以消灭目标位置上所有的BETA狗。
出于安全考虑,游戏系统已经保证不存在一个炮塔能够瞄准另外一个炮塔,即对于任意一个炮
塔,它所有可能的攻击位置上不存在另外一个炮塔。而且,如果把炮塔的起点和终点称为炮弹的运行
轨迹,那么系统不允许两条轨迹相交(包括起点和终点)。
现在,选定目标位置以后,每一个炮塔同时开炮,你要告诉Nick,他最多可以干掉多少BETA狗。
Input
第一行两个正整数n,m,表示地图的规模。
接下来礼行,每行m个整数,0表示空地,-1,-2,一3,-4分别表示瞄准上下左右的炮塔,若为正整
数p,则表示该位置有p个BETA狗。
n,m <= 50,每个位置的BETA狗数量不超过999个,保证不存在任意一个炮塔能够瞄准另外一个炮塔
Output
一个正整数,表示Nick最多可以干掉几个BETA狗
Sample Input
3 2
0 9
-4 3
0 -1
Sample Output
9
分析:

显然,题目保证了只有横炮台与纵炮台才可能会有相交的攻击轨迹。

然后对于每对有相交攻击范围的横炮台与纵炮台,它们对答案的贡献得分不仅决定于它们自己的攻击范围内的BETA狗,还会被其它的炮台所局限。所以,每个炮台对于进攻目标的选择,正好需要最大流最小割的类似自我调整的性质。

考虑如何连边。如果从最大流的角度思考,难以表达“炮台A选了BEAT狗a,炮台B就不能选a”这种逻辑关系,所以改换最小割。若一对纵横炮台A与B存在公共轨道,可以看成A到B有一条路径,就像这样:

那么我们割就是让两个炮台无法相交。

如果两个炮台要攻击最大值时都要去跨过它们攻击轨道的相交点,那么我们的割就要让其中一个炮台无法越过相交点,另一个不再受那个炮台的约束。

我们可以把所有点拿出来当一个部,每个炮台的轨道上的点依次连边。

若该轨道为纵向,则轨道上的第一个点与原点连边,方向与炮台方向相同,同理连第一个点与第二个点,方向与炮台相同(因为打到一个点时,它之前的点会被轨道覆盖,所以不能分别与原点连边),以此类推。若该轨道为横向,则第一个点与汇点连边,方向与炮台方向相反,以此类推。

又因为两个炮台之间的路径只能有一次拐弯,故拆点,左边的点表示纵向轨迹,右边的点表示横向轨迹,相同的点之间从左到右连一条边。

这样就可以表示出全部的纵炮到横炮的路径(纵横可以反过来)。

接下来考虑一下割边的代价。

我们先来考虑割边的意义。割某条边就代表有一个炮台打到的点只能是那个边的一个端点,而另外一个的炮台就不再受这个炮台的限制。

所以,首先满足的是割的边必须是同一条轨道上相邻点之间的边,所以 相同点之间的边 和 点与汇点,源点的边 的代价(即容量)为inf。这样它们就不会被割了。

对于其它边的讨论,容我摘一段xmy大佬的解释:

把炮塔能够打到的beta狗中的最大值记为mx,那么炮塔路径最多只会延伸到第一个mx,再往后只会更劣。我们先把每个炮塔的mx加入ans中。

对于竖炮塔的一条边u->v,割掉它表示炮塔打到了u点,那么ans就会损失掉mx-u点的beta狗的值,于是这条边的容量为mx-u点的beta狗。

对于横炮塔的一条边u->v,割掉它表示炮塔打到了v点,那么ans就会损失掉mx-v点的beta狗的值于是这条边的容量为mx-v点的beta狗。

所以答案就是ans-最小割。

最后附上代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define p(i,j) (i-1)*m+j
using namespace std;
const int maxp=,inf=0x3f3f3f3f;
int n,m,tot,map[][], dx[]={-,,,},dy[]={,,-,},d[maxp],vd[maxp];
int S,T,ans,cnt=,sum,info[maxp];
struct flow{int u,v,nex,w;}e[];
int sap(int i,int augco)
{
if(i==T)return augco;
int j,tmp,ret=,mind=T-;
for(int o=info[i];o;o=e[o].nex)
{
j=e[o].v;
if(e[o].w>){
if(d[i]==d[j]+)
{
tmp=sap(j,min(e[o].w,augco));
e[o].w-=tmp;
e[o^].w+=tmp;
ret+=tmp;
augco-=tmp;
if(d[]>=T)return ret;
if(augco==)break;
}
mind=min(mind,d[j]);
}
}
if(ret==)
{
vd[d[i]]--;
if(vd[d[i]]==)
d[]=T;
d[i]=mind+;
vd[d[i]]++;
}
return ret;
}
void solve()
{
memset(vd,,sizeof vd);
memset(d,,sizeof d);
vd[]=T;ans=;
while(d[S]<T)
ans+=sap(,inf);
}
void add(int u,int v,int w)
{
//printf("%d %d %d\n",u,v,w);
e[++cnt]=(flow){u,v,info[u],w};info[u]=cnt;
e[++cnt]=(flow){v,u,info[v],};info[v]=cnt;
}
int main()
{
scanf("%d%d",&n,&m);S=;T=+n*m+n*m+;
for(int i=;i<=n;i++)for(int j=;j<=m;j++)scanf("%d",&map[i][j]);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)if(map[i][j]<)
{
int k=-map[i][j]-,mx=,x,y;
map[i][j]=;
for(x=i+dx[k],y=j+dy[k];<=x&&x<=n&&<=y&&y<=m;x+=dx[k],y+=dy[k])mx=max(mx,map[x][y]);
sum+=mx;
if(k==||k==)
{
add(S,+p(i,j),inf);
for(x=i,y=j;map[x][y]!=mx;x+=dx[k],y+=dy[k])
add(+p(x,y),+p(x+dx[k],y+dy[k]),mx-map[x][y]);
}
if(k==||k==)
{
add(+n*m+p(i,j),T,inf);
for(x=i,y=j;map[x][y]!=mx;x+=dx[k],y+=dy[k])
add(+n*m+p(x+dx[k],y+dy[k]),+n*m+p(x,y),mx-map[x][y]);
}
}
for(int i=;i<=n*m;i++) add(+i,+n*m+i,inf);solve();
printf("%d\n",sum-ans);
}

[网络流]BZOJ4657 最小割约束的更多相关文章

  1. 【BZOJ2229】[ZJOI2011]最小割(网络流,最小割树)

    [BZOJ2229][ZJOI2011]最小割(网络流,最小割树) 题面 BZOJ 洛谷 题解 戳这里 那么实现过程就是任选两点跑最小割更新答案,然后把点集划分为和\(S\)联通以及与\(T\)联通. ...

  2. 【CF331E】Biologist(网络流,最小割)

    [CF331E]Biologist(网络流,最小割) 题面 洛谷 翻译: 有一个长度为\(n\)的\(01\)串,将第\(i\)个位置变为另外一个数字的代价是\(v_i\). 有\(m\)个要求 每个 ...

  3. 【BZOJ1391】Order(网络流,最小割)

    [BZOJ1391]Order(网络流,最小割) 题面 BZOJ权限题... 良心洛谷 题目描述 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成 ...

  4. 【BZOJ3144】切糕(网络流,最小割)

    [BZOJ3144]切糕(网络流,最小割) 题面 BZOJ 题解 这样的类型很有趣 先不考虑相邻距离差不能超过\(D\)的限制 我们考虑答案,显然就是在每个位置选一个最小的高度割就行了 化成最小割的模 ...

  5. [bzoj1497][NOI2006]最大获利_网络流_最小割

    最大获利 bzoj-1497 题目大意:可以建立一个点,花费一定的代价:将已经建立的两个点之间连边,得到一定收益.有些节点之间是不允许连边的. 注释:1<=点数<=5,000,1<= ...

  6. [TJOI2013]攻击装置(网络流,最小割)

    前言 网络流被hbx吊起来打 Solution 考虑一下这个走法是不是和象棋中马的走法一模一样(废话) 那么显然我每一次移动是走三次,如果将棋盘二分图染色一下,不就是每一次只能走到另一个颜色的吗? 然 ...

  7. [bzoj2561]最小生成树_网络流_最小割_最小生成树

    最小生成树 bzoj-2561 题目大意:题目链接. 注释:略. 想法: 我们发现: 如果一条权值为$L$的边想加入到最小生成树上的话,需要满足一下条件. 就是求出原图的最小生成树之后,这个边当做非树 ...

  8. cogs750栅格网络流(最小割)

    750. 栅格网络流 ★★☆   输入文件:flowa.in   输出文件:flowa.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] Bob 觉得一般图的最大流问题太 ...

  9. 【HDU 5855】Less Time, More profit(网络流、最小割、最大权闭合子图)

    Less Time, More profit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/O ...

随机推荐

  1. 用v-bind:style时的问题

    今天纠结了挺久一个问题,个人习惯是在HBuilder里先写好前端样式,在放.net去测试数据,但是发现一个问题 就是一个提示框跟随鼠标移动 提示框用v-bind:style绑定一个对象 DIV就是这句 ...

  2. Spring笔记

    Spring概念 Spring是一个开源的轻量级的框架 Spring核心主要两部分 (1) Aop面向切面编程,扩展功能不是修改源代码实现 (2) Ioc控制反转, 比如说有一个类,在类里面有方法(不 ...

  3. Android studio怎么使用自定义的framework而避免冲突报错和点不进去报红。

    文件:xx\project_abc\video\build.gradle保证可以运行到自定义的framework而不报错,可能因为project和module名字相同所以导致下面的路径是绝对路径,其他 ...

  4. 数据结构学习java(一点五)链式顺序表(链表)

    java中没有将指针暴露给用户(以前做过看过一篇文章写有java中是有指针的,只是被藏起来了),所以得使用引用的方式. 何为引用请看下面这篇文章(写的很不错,当然肯定比我写的好): https://w ...

  5. 卸载windows补丁

    wusa /uninstall /kb: wusa /uninstall /kb: 和某些应用软件冲突时,需要将上述补丁卸载.

  6. Docker-单宿主机下的网络模式

    docker利用namespaces和cgroups实现了应用隔离和资源控制,那么网络层优势如何实现的呢?是直接使用宿主机的网卡设备,还是独立创造出自己的网络设备?以及容器如何与外界通信,下面我们通过 ...

  7. Linux学习历程——Centos 7 find 命令

    一.命令介绍 find 命令用于按照指定条件来查找文件. 一些比较常用参数如下表 参数 作用 -name 匹配名称 -perm 匹配权限mode为完全匹配( –mode包含即可) -user 匹配所有 ...

  8. Windows Server(r12) - 配置 MySQL 远程访问

    Windows Server(r12) - 配置 MySQL 远程访问 工作主要为两部分, 一部分是 Windows 防火墙, 一部分是 MySQL 自身 Windows 端口远程访问 其实就是在 W ...

  9. Binwalk的安装和使用

    Binwalk的安装和使用 一.安装Git 参考链接:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067 ...

  10. java-环境变量的配置

    java基础教程 链接:https://pan.baidu.com/s/1dGHrkghUJi2lew8dbWlIvg 提取码:87mi