题目链接: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. 設定MacOS 終端機環境 (Homebrew/zsh/oh-my-zsh/iTerm2)

    安裝Homebrew 1 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/in ...

  2. POI之下载模板(或各种文件)

    该例基于Nutz框架 前台代码: <a href="" id="errordownload" onclick="downloadErrorLog ...

  3. css进阶之二:flex弹性布局

    布局模式是指一个盒子与其兄弟.祖先盒的关系决定其尺寸与位置的算法.css2.1中定义了四种布局模式,分别是块布局.行内布局.表格布局.以及定位布局.css3引入了新的布局模式Flexbox布局,灵活度 ...

  4. LeetCode~移除元素(简单)

    移除元素(简单) 1. 题目描述 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使 ...

  5. 【C#】WechatPay-API-v3 使用平台证书加密内容与应答|通知验签(SHA256 with RSA)

    官方暂时没有维护应答与通知签名的验证C#示例,找了些资料被困扰了一天终于调试通了,贴出来下 . 此类提供两个方法: 1.敏感信息加密,如身份证.银行卡号.(特约商户进件接口需要): 2.应答与通知签验 ...

  6. USB小白学习之路(2)端点IN/OUT互换

    端点2(out)和端点6(in)的out_in互换 注:这里的out和in都是以host为标准说的,out是host的out,在设备(Cy7c68013)这里其实是输入端口:in是host的in,在设 ...

  7. 【WPF学习】第五十三章 动画类型回顾

    创建动画面临的第一个挑战是为动画选择正确的属性.期望的结果(例如,在窗口中移动元素)与需要使用的属性(在这种情况下是Canvas.Left和Canvas.Top属性)之间的关系并不总是很直观.下面是一 ...

  8. preload & prefetch

    原文地址在 我的笔记里,觉得还行就给个 star 吧:) 关于 preload 和 prefetch 早有耳闻,知道它们可以优化页面加载速度,然具体情况却了解不多.搜索了相关的资料后对其有了些认识,在 ...

  9. 如何给女朋友讲SSM和springBoot的区别?(简单描述一下)

  10. js中的this和arguments.callee

    this和 arguments.callee this 全局作用域下,this指向Window 其他情况下,谁调用this就指向谁 console.log(this) //对调用就指向谁系列 func ...