题目描述

  有一个 \(n\times m\)的网格,每个格子里面可能有一些炮塔,或者有几个人。

  每个炮塔可以在给定的方向(上下左右)上选一个点作为它的攻击位置,然后消灭这个格子里面的所有人。当然也可以不进行攻击。

  要求两个炮弹的飞行轨迹不能相交。

  问你最多能打死多少个人。

  保证不存在一个炮塔可以攻击另一个炮塔的情况。

  \(n,m\leq 50,\) 每个格子的人数 \(< 1000\)

题解

  先忽略"要求两个炮弹的飞行轨迹不能相交"这个条件。

  那么可以把每个炮塔能攻击到的格子找出来,连成一条链,容量为前面这个格子的人数。

  但这样求出来的是最小值。

  用一个大整数去减掉每个数作为边权就好了。

  现在有"要求两个炮弹的飞行轨迹不能相交"这个条件。

  参考 HNOI2013这道题。

  可以把朝向为左右的炮塔的链的方向反过来,然后在相交的位置上连一条(竖着的炮塔那一列对应的格子 \(\to\) 横着的炮塔那一行对应的格子)的边,容量为 \(\infty\)。

  为什么这是对的?

  

  如果竖着的炮塔攻击的点超过了两条链的交点,横着的炮塔攻击的点也超过了两条链的交点,那么那条容量为 \(\infty\) 的边就一定会有流量经过,然后会沿着 \(S\to\) 交点 \(\to T\) 流到终点。所以这样建图就保证了如果竖着的炮塔攻击的点超过了两条链的交点,那么横着的炮塔攻击的点就不会超过了两条链的交点。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c,b=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c=='-')
{
c=getchar();
b=1;
}
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return b?-s:s;
}
void put(int x)
{
if(!x)
{
putchar('0');
return;
}
static int c[20];
int t=0;
while(x)
{
c[++t]=x%10;
x/=10;
}
while(t)
putchar(c[t--]+'0');
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
const int inf=0x7fffffff;
namespace flow
{
int v[100010];
int c[100010];
int t[100010];
int h[100010];
int cnt;
void add(int x,int y,int a)
{
cnt++;
v[cnt]=y;
c[cnt]=a;
t[cnt]=h[x];
h[x]=cnt;
}
int e[100010];
int d[100010];
int op(int x)
{
return ((x-1)^1)+1;
}
int S,T,num;
queue<int> q;
void bfs()
{
memset(d,-1,sizeof d);
q.push(T);
d[T]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
e[d[x]]++;
for(int i=h[x];i;i=t[i])
if(c[op(i)]&&d[v[i]]==-1)
{
d[v[i]]=d[x]+1;
q.push(v[i]);
}
}
}
int cur[100010];
int dfs(int x,int flow)
{
if(x==T)
return flow;
int s=0;
for(int &i=cur[x];i;i=t[i])
if(c[i]&&d[v[i]]==d[x]-1)
{
int u=dfs(v[i],min(flow,c[i]));
c[i]-=u;
c[op(i)]+=u;
flow-=u;
s+=u;
if(!flow)
return s;
}
e[d[x]]--;
if(!e[d[x]])
e[S]=num;
d[x]++;
e[d[x]]++;
cur[x]=h[x];
return s;
}
int solve()
{
bfs();
int ans=0;
memcpy(cur,h,sizeof h);
while(d[S]>=0&&d[S]<=num-1)
ans+=dfs(S,inf);
return ans;
}
}
void add(int x,int y,int z)
{
flow::add(x,y,z);
flow::add(y,x,0);
}
int n,m;
int a[100][100];
int b[100][100];
int main()
{
open("c");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
flow::S=1;
flow::T=2;
flow::num=2;
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]==-3)
{
if(j==1)
continue;
cnt++;
for(int k=j;k>=1;k--)
b[i][k]=++flow::num;
add(flow::S,b[i][1],1000-a[i][1]);
for(int k=1;k<j;k++)
add(b[i][k],b[i][k+1],1000-a[i][k+1]);
add(b[i][j],flow::T,1000);
}
else if(a[i][j]==-4)
{
if(j==m)
continue;
cnt++;
for(int k=j;k<=m;k++)
b[i][k]=++flow::num;
add(flow::S,b[i][m],1000-a[i][m]);
for(int k=j;k<m;k++)
add(b[i][k+1],b[i][k],1000-a[i][k]);
add(b[i][j],flow::T,1000);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]==-1)
{
if(i==1)
continue;
cnt++;
for(int k=1;k<=i;k++)
{
int v=++flow::num;
if(b[k][j])
add(v,b[k][j],inf);
b[k][j]=v;
}
add(flow::S,b[i][j],1000);
add(b[i][j],b[i-1][j],1000);
for(int k=i-1;k>1;k--)
add(b[k][j],b[k-1][j],1000-a[k][j]);
add(b[1][j],flow::T,1000-a[1][j]);
}
else if(a[i][j]==-2)
{
if(i==n)
continue;
cnt++;
for(int k=i;k<=n;k++)
{
int v=++flow::num;
if(b[k][j])
add(v,b[k][j],inf);
b[k][j]=v;
}
add(flow::S,b[i][j],1000);
add(b[i][j],b[i+1][j],1000);
for(int k=i+1;k<n;k++)
add(b[k][j],b[k+1][j],1000-a[k][j]);
add(b[n][j],flow::T,1000-a[n][j]);
}
int ans=flow::solve();
ans=cnt*1000-ans;
printf("%d\n",ans);
return 0;
}

【XSY2925】cti 网络流的更多相关文章

  1. JZOJ 5602.【NOI2018模拟3.26】Cti

    JZOJ 5602.[NOI2018模拟3.26]Cti Description 有一个 \(n×m\) 的地图,地图上的每一个位置可以是空地,炮塔或是敌人.你需要操纵炮塔消灭敌人. 对于每个炮塔都有 ...

  2. plain framework 1 网络流 缓存数据详解

    网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...

  3. 网络流模板 NetworkFlow

    身边的小伙伴们都在愉快地刷网络流,我也来写一发模板好了. Network Flow - Maximum Flow Time Limit : 1 sec, Memory Limit : 65536 KB ...

  4. COGS732. [网络流24题] 试题库

    «问题描述:假设一个试题库中有n道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取m 道题组成试卷.并要求试卷包含指定类型的试题.试设计一个满足要求的组卷算法.«编程任务: ...

  5. ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)

    //有流量上下界的网络流 //Time:47Ms Memory:1788K #include<iostream> #include<cstring> #include<c ...

  6. BZOJ 3144 [Hnoi2013]切糕 ——网络流

    [题目分析] 网络流好题! 从割的方面来考虑问题往往会得到简化. 当割掉i,j,k时,必定附近的要割在k-D到k+D上. 所以只需要建两条inf的边来强制,如果割不掉强制范围内的时候,原来的边一定会换 ...

  7. bzoj3572又TM是网络流

    = =我承认我写网络流写疯了 = =我承认前面几篇博文都是扯淡,我写的是垃圾dinic(根本不叫dinic) = =我承认这道题我调了半天 = =我承认我这道题一开始是T的,后来换上真正的dinic才 ...

  8. hdu3549还是网络流

    最后一次训练模板(比较熟练了) 接下来训练网络流的建图 #include <cstdio> #define INF 2147483647 int n,m,ans,x,y,z,M,h,t,T ...

  9. 二分图&网络流&最小割等问题的总结

    二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...

随机推荐

  1. JQuery显示,隐藏和淡入淡出效果

    为了把JQuery搞熟悉,看着菜鸟教程,一个一个例子打,边看边记,算是一晚上的一个小总结吧.加油,我很本但是我很勤奋啊.系统的了解它,就要花时间咯. <!DOCTYPE html> < ...

  2. Android 通过反射获取DatePicker 中的控件,并改变其颜色

    到最后也只是成功改变了中间部分的颜色. private void setDatePickerDividerColor(DatePicker datePicker) { // Divider chang ...

  3. 系统前端基本文件+ajax部分理解

    静态页面: 一.static: css dist fonts images js model 二.templates: html ajax搜索操作: <html> <head> ...

  4. 一个「学渣」从零开始的Web前端自学之路

    从 13 年专科毕业开始,一路跌跌撞撞走了很多弯路,做过餐厅服务员,进过工厂干过流水线,做过客服,干过电话销售可以说经历相当的“丰富”. 最后的机缘巧合下,走上了前端开发之路,作为一个非计算机专业且低 ...

  5. MySQL自增列(AUTO_INCREMENT)相关知识点总结

      MySQL的自增列(AUTO_INCREMENT)和其它数据库的自增列对比,有很多特性和不同点(甚至不同存储引擎.不同版本也有一些不同的特性),让人感觉有点稍微复杂.下面我们从一些测试开始,来认识 ...

  6. C#中的值类型和引用类型,深拷贝,浅拷贝

    from https://www.jianshu.com/p/2d27b06e253f 一.C#中的值类型和引用类型 概念 值类型直接存储其值. 引用类型存储对值的引用. 说起来有些拗口,其本质是Va ...

  7. MPP架构海量数据分析仓库——Greenplum介绍

    一.Greenplum背景 时间回到2002年,互联网行业经过近10年的发展,数据量正处于快速增长期: 1.传统的主机计算模式在海量数据面前,除了造价昂贵外,在CPU计算和IO吞吐上不能满足海量数据的 ...

  8. Python XML解析之DOM

    DOM说明: DOM:Document Object Model API DOM是一种跨语言的XML解析机制,DOM把整个XML文件或字符串在内存中解析为树型结构方便访问. https://docs. ...

  9. SQLServer之UNIQUE约束

    UNIQUE约束添加规则 1.唯一约束确保表中的一列数据没有相同的值. 2.与主键约束类似,唯一约束也强制唯一性,但唯一约束用于非主键的一列或者多列的组合,且一个表可以定义多个唯一约束. 使用SSMS ...

  10. Python基础——7面向对象高级编程

    实例与类动态添加方法 实例添加属性: def Student(object): pass s = Student() s.name = ‘syz’ 实例添加方法 from types import M ...