BZOJ 1066 蜥蜴 最大流
题目链接:
https://www.lydsy.com/JudgeOnline/problem.php?id=1066
题目大意:
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。求无法逃离的蜥蜴总数的最小值。
思路:
网络流拆点建图。
对于每个石柱进行拆成两个点,然后在这两个点中限制最大流为石柱高度,这样保证经过石柱的次数,对于两个可以互相到达的点从一个点的出点往另一个入点连边,容量为INF,对于可以跳出界的点往汇点连边,对于有蜥蜴的点从源点向其连边。
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#define Accepted 0
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快
const int INF = 1e9 + ;
const double eps = 1e-;
struct edge
{
int u, v, c, f;
edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
};
vector<edge>e;
vector<int>G[maxn];
int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化
int m;
void init(int n)
{
for(int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c)
{
//cout<<u<<" "<<v<<" "<<c<<endl;
e.push_back(edge(u, v, c, ));
e.push_back(edge(v, u, , ));
m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{
memset(level, -, sizeof(level));
queue<int>q;
level[s] = ;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int v = ; v < G[u].size(); v++)
{
edge& now = e[G[u][v]];
if(now.c > now.f && level[now.v] < )
{
level[now.v] = level[u] + ;
q.push(now.v);
}
}
}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{
if(u == t)return f;//已经到达源点,返回流量f
for(int &v = iter[u]; v < G[u].size(); v++)
//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
//在每次找增广路的时候,数组要清空
{
edge &now = e[G[u][v]];
if(now.c - now.f > && level[u] < level[now.v])
//now.c - now.f > 0表示这条路还未满
//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
{
int d = dfs(now.v, t, min(f, now.c - now.f));
if(d > )
{
now.f += d;//正向边流量加d
e[G[u][v] ^ ].f -= d;
//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
return d;
}
}
}
return ;
}
int Maxflow(int s, int t)
{
int flow = ;
for(;;)
{
BFS(s);
if(level[t] < )return flow;//残余网络中到达不了t,增广路不存在
memset(iter, , sizeof(iter));//清空当前弧数组
int f;//记录增广路的可增加的流量
while((f = dfs(s, t, INF)) > )
{
flow += f;
}
}
return flow;
}
struct node
{
int x, y;
node(){}
node(int x, int y):x(x), y(y){}
bool operator < (const node& a)const
{
return x < a.x || x == a.x && y < a.y;
}
};
map<node, int>ID;
char Map[][];
int main()
{
int n, m, d;
scanf("%d%d%d", &n, &m, &d);
int tot = ;
for(int i = ; i < n; i++)
{
scanf("%s", Map[i]);
for(int j = ; j < m; j++)
{
if(Map[i][j] != '')
{
ID[node(i, j)] = ++tot;
addedge(tot, tot + , Map[i][j] - '');
if(i < d || j < d || n - i <= d || m - j <= d)
addedge(tot + , , INF);
}
}
}
for(int i = ; i < n; i++)
{
for(int j = ; j < m; j++)
{
if(Map[i][j] != '')
for(int x = -d; x <= d; x++)
{
for(int y = -d; y <= d; y++)
{
int xx = x + i;
int yy = y + j;
if(xx >= && xx < n && yy >= && yy < m && (xx != i || yy != j) && Map[xx][yy] != '')
{
if(abs(i - xx) + abs(j - yy) <= d)addedge(ID[node(i, j)] + , ID[node(xx, yy)], INF);
}
}
}
}
}
int cnt = ;
for(int i = ; i < n; i++)
{
scanf("%s", Map[i]);
for(int j = ; j < m; j++)if(Map[i][j] == 'L')
{
addedge(, ID[node(i, j)], );
cnt++;
}
}
cout<<cnt-Maxflow(, )<<endl;
return Accepted;
}
BZOJ 1066 蜥蜴 最大流的更多相关文章
- bzoj 1066 蜥蜴
最大流. 建图:首先将每根柱子拆成两个点. 每根柱子的入点向出点连一条容量为柱子高度的边. 每根柱子的出点向可以到达的柱子的入点连一条容量为正无穷的边. 源点向每根初始有蜥蜴的柱子的入点连一条容量为一 ...
- BZOJ 1066 蜥蜴(网络流)
很普通的拆点网络流,把每个柱子拆成两个点(i,j,0)和(i,j,1).对于柱子的高度限制则加边((i,j,0),(i,j,1),height). 两个柱子能互相到达则加边((i,j,1),(i1,j ...
- [BZOJ 1066] [SCOI2007] 蜥蜴 【最大流】
题目链接:BZOJ - 1066 题目分析 题目限制了高度为 x 的石柱最多可以有 x 只蜥蜴从上面跳起,那么就可以用网络流中的边的容量来限制.我们把每个石柱看作一个点,每个点拆成 i1, i2,从 ...
- POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流)
POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流) Description Yo ...
- poj 2711 Leapin' Lizards && BZOJ 1066: [SCOI2007]蜥蜴 最大流
题目链接:http://poj.org/problem?id=2711 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1066 Your p ...
- BZOJ 1066 [SCOI2007]蜥蜴(最大流)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1066 [题目大意] 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些 ...
- BZOJ 1066: [SCOI2007]蜥蜴( 最大流 )
结点容量..拆点然后随便写 --------------------------------------------------------------- #include<cstdio> ...
- BZOJ 1066:[SCOI2007]蜥蜴(最大流)
蜥蜴Description在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到 ...
- AC日记——[SCOI2007]蜥蜴 bzoj 1066
1066 思路: 网络流最大流: 拆点,每个点拆成两个,流量为这个点的高度: 注意,文中说的距离是曼哈顿距离(劳资以为开根号wa了不知道多少次): 每两个距离不大于d的点连边,流量inf: 如果距离能 ...
随机推荐
- [android] 手机卫士黑名单功能(短信拦截)
前面我们把需要拦截的手机号都存储和展示出来了,接下来是使用广播接收者拦截短信了,这个广播接收者需要和一个服务绑定,服务开启的时候,接收者存在,服务停掉时,接收者关闭 在service包下定义一个类Ca ...
- [javaSE] 数组(查找-二分查找)
前提数组必须是有序的 定义最小,最大,中间的角标索引 int min,max,mid; min=0; max=arr.length-1; mid=(min+max)/2; 上面的索引需要变化,使用循环 ...
- xmpp实现的即时通讯聊天(二)
参考网址:http://www.jianshu.com/p/8894a5a71b70 借图描述原理: 三.注册.登陆.聊天功能的实现 故事板如下: 四个类如下: 不喜多言,直接上Demo: Login ...
- ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock 问题修改
ubuntu 常见错误–Could not get lock /var/lib/dpkg/lock 通过终端安装程序sudo apt-get install xxx或者apt-get update时出 ...
- WCF中DataContract和MessageContract的区别
一.代码案例 首选建立2个WCF Service,它们分别使用不同的Contract,同时创建一个Console控制台项目,作为Client: 其中,WcfServiceWithDataContrac ...
- JVM垃圾回收器之G1(Garbage First)--new
相比CMS收集器有两个显著的改进: (1). G1收集器是基于“标记-整理”算法实现的收集器,不会产生空间碎片 (2). 它可以精确地控制停顿,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在 ...
- pipenv虚拟环境和依赖管理工具
一.pipenv用来干嘛 每门编程语言发展到现在,都需要一个工具,能够管理代码版本和控制生产环境和测试环境依赖一致的,这样减少不可代码上线之后不可控的问题出现.Php有Composer.Nodejs有 ...
- 产品相关 细说软件产品和业务 & 业务过程(流程) & 业务逻辑
细说软件产品和业务& 业务过程(流程) & 业务逻辑 by:授客 QQ:1033553122 作为一名测试人猿,需要懂产品,不懂产品的测试猿不是好测试猿猴.而业务逻辑是软件产品 ...
- linux 权限管理命令chown、chgrp、umask、linux新建文件或目录的默认权限755
chown /bin/chownchown [用户] [文件或目录] 改变文件或目录的所有者只有root可以改变文件或目录的所有者 root用户:mkdir /tmptouch /tmp/test.f ...
- 神奇的负Margin
在做slide时候一般都是采用父元素超宽+overflow的做法,今天发现了用margin-right:-100%;可以让子元素全部重叠起来.效果也是不错的