题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2732

题目给定一个场景,有n*m个方格,每个方格代表一个柱子,一个柱子可以承受不同次数的跳跃,开始时图中给定一些地方有蜥蜴,并且给定蜥蜴最多跳跃的步长,只要跳到方格之外就能安全,而且每只蜥蜴不能在同一个地方重合,每次蜥蜴跳离一个地方这个地方的柱子就的承受次数就会减一,问最终会有多少只蜥蜴不能跳出迷宫。

这个问题可以这样思考,每次蜥蜴跳出一个位置之后这个位置的“资源”就会减少1,而这个减少之后的“资源”不可以再利用,而且涉及到点之间的转移,这在图论中和最大流很相似,所以我们想到可不可以将点转化成状态,地图中的每一个位置(i,j)(0<=i,j<n)可以通过i*m+j+1转化成[1,n*m]闭区间之内的位置,所以我们可以把这个设为他的id,可以将点位置拆开成两个,一个是id,表示没有转移时的状态,另一个点是id+n*m,表示这个点拆开之后的另一个状态。设置一个超级源和一个超级汇。

转换策略如下:

①、如果一个点位置(i,j)值num大于0,那么可以连边(id,id+n*m,num),表示最多有num次“流”在这个位置转换,num个用完也就代表不能发生转换,也就是这个位置不能站蜥蜴了。

②、如果一个位置通过跳跃d可以到达外围就设置边(id,T,inf),就是把这个位置和超级汇连接起来,并且不限制从这里通过的蜥蜴的数量。

③、如果一个位置有蜥蜴,我们可以把这个位置和超级源连接在一起,也就是(S,id,1)1表示在这个位置有一只蜥蜴出发。就相当于把蜥蜴放在一个源点,蜥蜴数量便是源点流量。

④、两个位置之间的距离(横纵坐标绝对值之差)如果小于d那就可以转换,注意连的边是(id+n*m,id2,1),因为在他跳出当前位置时必须当前位置的承受容量减一,所以必须重跳完之后的状态转移。

基本思想就是拆点。需要慎重思考转移的方式。

 #include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a))
#define prime1 1e9+7
#define prime2 1e9+9
#define pi 3.14159265
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define scand(x) scanf("%llf",&x)
#define f(i,a,b) for(int i=a;i<=b;i++)
#define scan(a) scanf("%d",&a)
#define mp(a,b) make_pair((a),(b))
#define P pair<int,int>
#define dbg(args) cout<<#args<<":"<<args<<endl;
#define inf 0x7ffffff
inline int read(){
int ans=,w=;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-;ch=getchar();}
while(isdigit(ch))ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
return ans*w;
}
const int maxn=;
const int maxm=;
struct flow{
int s,t;
int head[maxn],nxt[maxm],d[maxn],cur[maxn];//cur当前弧优化
bool vis[maxn];
struct node{
int u,v,w;
}p[maxm];
int e;
void init()
{
e=;
mem(head,-);
mem(nxt,-);
}
void addedge(int u,int v,int w)//顺带添加反向边
{
p[e].u=u;
p[e].v=v;
p[e].w=w;
nxt[e]=head[u];
head[u]=e++;
p[e].u=v;
p[e].v=u;
p[e].w=;
nxt[e]=head[v];
head[v]=e++;
}
bool bfs(int src,int sink)//确定bfs序
{
mem(vis,);
mem(d,);
d[src]=;
vis[src]=;
queue<int> q;
q.push(src);
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=head[cur];~i;i=nxt[i])
{
int v=p[i].v;
if(!vis[v]&&p[i].w)//确定这个点没有被标号,并且不是反向边
{
vis[v]=;
d[v]=d[cur]+;
q.push(v);
}
}
}
if(d[sink])return true;
return false;
}
int dfs(int s,int flow)
{
if(s==t)return flow;
int used=;
for(int& i=cur[s];~i;i=nxt[i])
{
int v=p[i].v,w=p[i].w;
if(d[v]==d[s]+&&w>)//根据Dinic算法的思想,只能走正向的、bfs序大一的边
{
int tmp=dfs(v,min(flow-used,w));
if(tmp>)
{
p[i].w-=tmp;//更新正向边的流量以及反向边的流量,
p[i^].w+=tmp;//正向边是偶数,它对应的反向边就是正向边+1
used+=tmp;//从一个点出发最多的流量是flow,用掉的流量需要更新
if(used==flow)break;
}
}
}
if(!used)d[s]=;//从该点出发的流不能被使用,所以这个点在这次搜索中被丢弃
return used;
}
int dinic()
{
int ans=;
while(bfs(s,t))
{
memcpy(cur,head,sizeof(head));
ans+=dfs(s,inf);
}
return ans;
}
}a;
int d;
int t;
char s[];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
std::ios::sync_with_stdio(false);
t=read();
int n,m;
int kase=;
while(t--)
{
a.init();
int cnt=;
n=read(),d=read();
f(i,,n-)
{
scanf(" %s",s);
if(i==)
{
m=strlen(s);
// a.n=2*n*m+2;//最大流中点的数量设置
a.s=;
a.t=*n*m+;//设置超级源与超级汇
}
f(j,,m-)
{
int num=s[j]-'';
if(num>)//将大于零的格子拆开成两个格子,并连线,
{
int id=i*m+j+;
a.addedge(id,id+n*m,num);
if(i-d<||i+d>=n||j-d<||j+d>=m)
{
a.addedge(id+n*m,a.t,inf);//可以到达安全地点,且流的大小不限制
}
else
{
f(k,,n-)//由于图的大小不大,所以可以枚举每一个位置检查是否可行
f(l,,m-)
{
int id2=k*m+l+;
if(id==id2)continue;
if(abs(i-k)+abs(j-l)<=d)
a.addedge(id+n*m,id2,inf);//从id位置能够跳到id2位置,但是记住一定是在id位置少1之后的结点上
}
}
}
}
}
f(i,,n-)
{
scanf(" %s",s);
f(j,,m-)
{
if(s[j]=='L')//记录蜥蜴的数量并与超级源连线,
{
cnt++;
int id=i*m+j+;
a.addedge(a.s,id,);
}
}
}
int ans=cnt-a.dinic();
if(ans==)pf("Case #%d: no lizard was left behind.\n",++kase);
else if(ans==)pf("Case #%d: 1 lizard was left behind.\n",++kase);
else pf("Case #%d: %d lizards were left behind.\n",++kase,ans); }
}

hdu2732 最大流+拆点的更多相关文章

  1. poj 3498 March of the Penguins(最大流+拆点)

    题目大意:在南极生活着一些企鹅,这些企鹅站在一些冰块上,现在要让这些企鹅都跳到同一个冰块上.但是企鹅有最大的跳跃距离,每只企鹅从冰块上跳走时会给冰块造成损害,因此企鹅跳离每个冰块都有次数限制.找出企鹅 ...

  2. poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap

    poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...

  3. hdu2732 Leapin' Lizards 最大流+拆点

    Your platoon of wandering lizards has entered a strange room in the labyrinth you are exploring. As ...

  4. 最大流拆点——hdu2732,poj3436

    一种很普遍的做法就是把一个带有容量的点拆成两个点,一个入点一个出点,链接两个点的边的权值为这个点的容量 hdu3732 #include<cstdio> #include<cstri ...

  5. hdu4289 最小割最大流 (拆点最大流)

    最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...

  6. BZOJ-1877 晨跑 最小费用最大流+拆点

    其实我是不想做这种水题的QWQ,没办法,剧情需要 1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1704 Solve ...

  7. BZOJ-1070 修车 最小费用最大流+拆点+略坑建图

    1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3624 Solved: 1452 [Submit][Status] ...

  8. hdu 4289 最大流拆点

    大致题意:     给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 大致思路:     最基础的拆点最大 ...

  9. 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】

    题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...

随机推荐

  1. 阿里云ECS 实例Centos7系统磁盘扩容

    需求:一台阿里云的数据盘磁盘空间不足,需要扩容,我这里只有一个主分区,ext4文件系统. 因为磁盘扩容场景不同,阿里云的文档比较全面一些,所以先奉上阿里云的文档,下面开始我的操作步骤: 1.登录控制台 ...

  2. History of AI

    人工智能的历史源远流长.在古代的神话传说中,技艺高超的工匠可以制作人造人,并为其赋予智能或意识.[1]现代意义上的AI始于古典哲学家用机械符号处理的观点解释人类思考过程的尝试.20世纪40年代基于抽象 ...

  3. uniq命令使用方法

    uniq命令的作用:显示唯一的行,对于那些连续重复的行只显示一次! 接下来通过实践实例说明: [root@stu100 ~]# cat test boy took bat home boy took ...

  4. Event Loop事件循环,GET!

    JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...

  5. Android注解支持Support Annotations详解

    ###注解支持(Support Annotations)Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现 ...

  6. Microsoft Translator:消除面对面交流的语言障碍

    ​ Translator:消除面对面交流的语言障碍" title="Microsoft Translator:消除面对面交流的语言障碍"> ​ James Simm ...

  7. Chrome 插件安装时报错: "CRX_HEADER_INVALID"

    1. 将 crx 插件后缀名改为 rar 2. 解压 rar 包 3. 进入浏览器 1). 点击Chrome浏览器地址栏最右边的三个点 --> 更多工具 --> 扩展插件 --> 点 ...

  8. 身为 Java 程序员必须掌握的 10 款开源工具!

    本文主要介绍Java程序员应该在Java学习过程中的一些基本和高级工具.如果你是一位经验丰富的Java开发人员,你可能对这些工具很熟悉,但如果不是,现在就是是开始学习这些工具的好时机.Java世界中存 ...

  9. 我厌倦了 Redux,那就造个轮子 Rectx:第三集

    仓库:215566435/rectx 前言 麻烦快去我的仓库里面喷: 老子学不动了,求不要更新. 呵呵,你没想到吧,这玩意儿竟然有第三集!我靠,我自己都没想到,让我们悄悄的回顾一下前两集完全没想到,竟 ...

  10. cordova+vue打包ios调用相机闪退解决

    cordova+vue项目打包android,打开相机正常使用,但是打包ios后,需要多几个配置,才能打开,否则当调用的时候会闪退,上配置图 需要在选中的文件里面添加 <key>NSCam ...