hdu2732 最大流+拆点
题目链接: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 最大流+拆点的更多相关文章
- poj 3498 March of the Penguins(最大流+拆点)
题目大意:在南极生活着一些企鹅,这些企鹅站在一些冰块上,现在要让这些企鹅都跳到同一个冰块上.但是企鹅有最大的跳跃距离,每只企鹅从冰块上跳走时会给冰块造成损害,因此企鹅跳离每个冰块都有次数限制.找出企鹅 ...
- poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap
poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...
- hdu2732 Leapin' Lizards 最大流+拆点
Your platoon of wandering lizards has entered a strange room in the labyrinth you are exploring. As ...
- 最大流拆点——hdu2732,poj3436
一种很普遍的做法就是把一个带有容量的点拆成两个点,一个入点一个出点,链接两个点的边的权值为这个点的容量 hdu3732 #include<cstdio> #include<cstri ...
- hdu4289 最小割最大流 (拆点最大流)
最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...
- BZOJ-1877 晨跑 最小费用最大流+拆点
其实我是不想做这种水题的QWQ,没办法,剧情需要 1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1704 Solve ...
- BZOJ-1070 修车 最小费用最大流+拆点+略坑建图
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3624 Solved: 1452 [Submit][Status] ...
- hdu 4289 最大流拆点
大致题意: 给出一个又n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 大致思路: 最基础的拆点最大 ...
- 洛谷 P2764 最小路径覆盖问题【最大流+拆点+路径输出】
题目链接:https://www.luogu.org/problemnew/show/P2764 题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V ...
随机推荐
- python Post 登录 cookies 和session
def post_name(): print('\npost name') # http://pythonscraping.com/pages/files/form.html data = {'fir ...
- 前端开发个人小结 · Retrospection的博客
序 2018年转眼来到了最后一个月,算下来我进入前端之门也有一年了,虽然下半年由于忙于筹备毕业论文的相关事项,前端这一块有所放下,但是想想还是给自己这一年的学习做一个总结. 现代化软件开发确实是一个复 ...
- 用PHP实现的快速排序算法(支持记录原始数组下标)
代码如下 <?php /** * 快速排序 */ define("MAX_LENGTH_INSERT_SORT", 7); class QuickSort { /** * 交 ...
- c++获取屏幕大小
API: 要取得屏幕大小,可以用下面几个函数: # include <windows.h>int cx = GetSystemMetrics( SM_CXFULLSCREEN ); int ...
- 曹工说Spring Boot源码(22)-- 你说我Spring Aop依赖AspectJ,我依赖它什么了
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- springboot创建,自动装配原理分析,run方法启动
使用IDEA快速创建一个springboot项目 创建Spring Initializr,然后一直下一步下一步直至完成 选择web,表示创建web项目 运行原理分析 我们先来看看pom.xml文件 核 ...
- python大佬养成计划----HTML网页设计(序列)
序列化标签 1.有序标签--ol和li 有序列表标签是<ol>,是一个双标签.在每一个列表项目前要使用<li>标签.<ol>标签的形式是带有前后顺序之分的编号.如果 ...
- tab 切换下划线跟随实现
HTML 结构如下: <ul> <li class="active">不可思议的CSS</li> <li>导航栏</li> ...
- Yuchuan_Linux_C编程之六 Makefile项目管理
一.整体大纲 二.makefile的编写 一个规则 两个函数 三个变量 1. 一个规则 三要素:目标, 依赖, 命令 目标:依赖 命令: 第一条规则是用来生成终 ...
- .Net vs .Net Core,我改如何选择?看这一篇文章就够了
前言 .Net目前支持构建服务器端应用程序的两种实现主要有两种,.NET Framework和.NET Core.两者共享许多相同的组件,并且您可以在两者之间共享代码.但是,两者之间存在根本差异,在我 ...