【bzoj1066】[SCOI2007]蜥蜴 网络最大流
【bzoj1066】[SCOI2007]蜥蜴
Description
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
Input
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
Output
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
Sample Input
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..
Sample Output
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=3
代码
对于每根石柱,采取一分为二的想法,即把一个点分为两个点(可抽象为石柱底部到顶部),其连线容量限制为石柱高度。
超级源与所有有蜥蜴的点相连,容量为1。
超级汇与地图内所有能跳出的点的底端相连,容量为INF。
对于地图内任意两个石柱,如果间距小于d,就将其中一根石柱的底部与另一根石柱的顶部相连,其连线容量为INF。
构图完成,剩下就是跑一遍最大流,然后用蜥蜴数量减去最大流就是最终结果。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//***************************
namespace NetFlow
{
const int MAXN=,MAXM=,inf=1e9;
struct Edge
{
int v,c,f,nx;
Edge() {}
Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
N=_n,sz=;
memset(G,-,sizeof(G[])*N);
}
void link(int u,int v,int c)
{
E[sz]=Edge(v,c,,G[u]);
G[u]=sz++;
E[sz]=Edge(u,,,G[v]);
G[v]=sz++;
}
int ISAP(int S,int T)
{
//S -> T
int maxflow=,aug=inf,flag=false,u,v;
for (int i=; i<N; ++i)cur[i]=G[i],gap[i]=dis[i]=;
for (gap[S]=N,u=pre[S]=S; dis[S]<N; flag=false)
{
for (int &it=cur[u]; ~it; it=E[it].nx)
{
if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+)
{
if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
pre[v]=u,u=v;
flag=true;
if (u==T)
{
for (maxflow+=aug; u!=S;)
{
E[cur[u=pre[u]]].f+=aug;
E[cur[u]^].f-=aug;
}
aug=inf;
}
break;
}
}
if (flag) continue;
int mx=N;
for (int it=G[u]; ~it; it=E[it].nx)
{
if (E[it].c>E[it].f&&dis[E[it].v]<mx)
{
mx=dis[E[it].v];
cur[u]=it;
}
}
if ((--gap[dis[u]])==) break;
++gap[dis[u]=mx+];
u=pre[u];
}
return maxflow;
}
bool bfs(int S,int T)
{
static int Q[MAXN];
memset(dis,-,sizeof(dis[])*N);
dis[S]=;
Q[]=S;
for (int h=,t=,u,v,it; h<t; ++h)
{
for (u=Q[h],it=G[u]; ~it; it=E[it].nx)
{
if (dis[v=E[it].v]==-&&E[it].c>E[it].f)
{
dis[v]=dis[u]+;
Q[t++]=v;
}
}
}
return dis[T]!=-;
}
int dfs(int u,int T,int low)
{
if (u==T) return low;
int ret=,tmp,v;
for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx)
{
if (dis[v=E[it].v]==dis[u]+&&E[it].c>E[it].f)
{
if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
{
ret+=tmp;
E[it].f+=tmp;
E[it^].f-=tmp;
}
}
}
if (!ret) dis[u]=-;
return ret;
}
int dinic(int S,int T)
{
int maxflow=,tmp;
while (bfs(S,T))
{
memcpy(cur,G,sizeof(G[])*N);
while (tmp=dfs(S,T,inf)) maxflow+=tmp;
}
return maxflow;
}
}
using namespace NetFlow;
double dist(int a,int b,int x,int y)
{
return sqrt((b-y)*(b-y)+(a-x)*(a-x));
}
int main()
{
int n,m,d;
char mp[][],mp2[][];
cin>>n>>m>>d;
init();
for(int i=; i<=n; i++)
{
scanf("%s",mp[i]+);
}
for(int i=; i<=n; i++)
{
scanf("%s",mp2[i]+);
}
for(int i=; i<=n; i++)
{
for(int j=; j<=m; j++)
{
if((mp[i][j]-'')>)
{
for(int h=i-d; h<=i+d; h++)
{
for(int k=j-d; k<=j+d; k++)
{
if(h==i&&j==k)continue;
if(h<||k<||h>n+||k>m+)
continue;
double dd=d*1.0;
if(dist(i,j,h,k)>dd)continue;
if(h==||k==||h==n+||k==m+)
link((i-)*m+j+,,inf);
else link((i-)*m+j+,(h-)*m+k,inf);
}
}
link((i-)*m+j,(i-)*m+j+,mp[i][j]-'');
} }
}
int sum=;
for(int i=; i<=n; i++)
{
for(int j=; j<=m; j++)
{
if(mp2[i][j]=='L')
{
sum++;
link(,(i-)*m+j,);
}
}
}
cout<<sum-dinic(,)<<endl;
return ;
}
补:
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 1e3+, M = 1e3+, mod = 1e9+, inf = 2e9; char s[];
int head[N],S,T,r,c,d,t=,h[N],height[][],q[N],ans;
struct edge{int to,next,v;}e[N*N];
void adds(int u,int v,int w) {e[t].next=head[u];e[t].to=v;e[t].v=w;head[u]=t++;}
void add(int u,int v,int w) {adds(u,v,w);adds(v,u,);} bool bfs() {
memset(h,-,sizeof(h));
int l = , r = ,now;
q[l] = S;
h[S] = ;
while(l!=r) {
now=q[l++];if(l == ) l=;
for(int i=head[now];i;i=e[i].next) {
if(e[i].v&&h[e[i].to]==-) {
h[e[i].to] = h[now] + ;
q[r++]=e[i].to;
if(r == ) r = ;
}
}
}
if(h[T] == -) return ;
return ;
}
int dfs(int x,int f) {
if(x == T) return f;
int used=,w;
for(int i=head[x];i;i=e[i].next) {
if(e[i].v&&h[e[i].to] == h[x]+) {
w = dfs(e[i].to,min(f-used,e[i].v));
used+=w;e[i].v-=w;e[i^].v+=w;
if(used == f) return f;
}
}
return used;
}
void dinic() {while(bfs()) ans+=dfs(S,inf);} double dis(int i,int j,int k,int h) {return sqrt(1.0*(i-k)*(i-k) + 1.0*(j-h)*(j-h));}
int main() {
scanf("%d%d%d",&r,&c,&d);
S=*r*c,T=S+;
for(int i = ; i <= r; ++i)
{
scanf("%s",s+);
for(int j = ; j <= c; ++j)
{
height[i][j] = s[j]-'';
add((i-)*c+j,(i-)*c+j+r*c,height[i][j]);
if(i-d<=||j-d<=||i+d>r||j+d>c)
{
add((i-)*c+j+r*c,T,inf);
}
}
}
int sum = ;
for(int i = ; i <= r; ++i)
{
scanf("%s",s+);
for(int j = ; j <= c; ++j) {
if(s[j] == 'L')
{
sum++;
add(S,(i-)*c+j,);
}
for(int k = ; k <= r; ++k)
for(int h = ; h <= c; ++h) {
if((k!=i||j!=h) && dis(i,j,k,h) <= 1.0*d)
{
add((i-)*c+j+r*c,(k-)*c+h,inf);
}
}
}
}
dinic();
printf("%d\n",sum-ans);
//cout<<sum-ans<<endl;
return ;
}
dinic
【bzoj1066】[SCOI2007]蜥蜴 网络最大流的更多相关文章
- bzoj1066: [SCOI2007]蜥蜴(最大流)
1066: [SCOI2007]蜥蜴 题目:传送门 题解: 哇QTT大佬一眼秒算法...ORT 其实很容易就可以看出来是一道最大流 因为有边的使用限制,那么就可以直接当成是流量来处理嘛 因为是对点进行 ...
- BZOJ1066 [SCOI2007]蜥蜴 网络流 最大流 SAP
由于本题和HDU2732几乎相同,所以读者可以看-> HDU2732题解传送门: http://www.cnblogs.com/zhouzhendong/p/8362002.html
- BZOJ1066 SCOI2007 蜥蜴 【网络流-最大流】
BZOJ1066 SCOI2007 蜥蜴 Description 在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离 ...
- 【bzoj1066】: [SCOI2007]蜥蜴 图论-最大流
[bzoj1066]: [SCOI2007]蜥蜴 把石柱拆点,流量为高度 然后S与蜥蜴连流量1的边 互相能跳到的石柱连inf的边 石柱能到边界外的和T连inf的边 然后跑dinic就好了 /* htt ...
- P2472 [SCOI2007]蜥蜴(最大流)
P2472 [SCOI2007]蜥蜴 自己第一道独立做题且一遍AC的网络流题纪念... 看到这道题我就想到网络流建图的方式了... 首先根据每个高度,我们将每个点拆成两个点限流.之后根据跳的最大距离, ...
- bzoj千题计划135:bzoj1066: [SCOI2007]蜥蜴
http://www.lydsy.com/JudgeOnline/problem.php?id=1066 每个柱子拆成两个点 i<<1,i<<1|1,之间连流量为高度的边 如果 ...
- 【BZOJ】1066: [SCOI2007]蜥蜴(最大流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1066 本题想一想应该懂了的. 我们想啊,,每个点都有限制,每个点都可以跳到另一个有限制的点,每个有蜥 ...
- BZOJ1066 [SCOI2007]蜥蜴
首先...这是道(很水的)网络流 我们发现"每个时刻不能有两个蜥蜴在同一个柱子上"这个条件是没有用的因为可以让外面的先跳,再让里面的往外跳 但是还有柱子高度的限制,于是把柱子拆点为 ...
- [BZOJ 1066] [SCOI2007] 蜥蜴 【最大流】
题目链接:BZOJ - 1066 题目分析 题目限制了高度为 x 的石柱最多可以有 x 只蜥蜴从上面跳起,那么就可以用网络流中的边的容量来限制.我们把每个石柱看作一个点,每个点拆成 i1, i2,从 ...
随机推荐
- mySQL 增量备份方案(转)
1.在 /etc/my.cnf 下面设置开启bin-log 编辑 vim /etc/my.cnf [mysqld] binlog_format = MIXED ...
- http https 区别
HTTPS和HTTP的区别 一.https协议需要到ca申请证书,一般免费证书很少,需要交费. 二.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议. 三. ...
- WPF 显示gif
using System; using System.IO; using System.Collections.Generic; using System.Windows; using System. ...
- (转)MFC的一些宏的整理 (DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)
很早看了MFC的一些宏的实现,什么RUNTIME_CLASS, DECLARE_DYNAMIC, DECLARE_DYNCREATE,IMPLEMENT_DYNCREATE, etc,看了就烦,现在整 ...
- linux下查看当前用户的 三个命令
linux下查看当前用户的 三个命令 1,whoami; 2,id -un; 3,who -H 可以列出当前所有的 NAME (用户名) LINE (窗口列表) TIME(开启时间 ...
- C++中的异常处理(三)
C++中的异常处理(三) 标签: c++C++异常处理 2012-11-24 23:00 1520人阅读 评论(0) 收藏 举报 分类: 编程常识(2) 版权声明:本文为博主原创文章,未经博主允许 ...
- centos linux从无到有安装wordpress
序:本博客从无到有搭建wordpress,包括从服务器和域名购买,会将步骤一步一步记录下来.如果你也是新手,那你有福了,因为我的系统是centos,对号入座啊. 目录 一.准备域名和服务器一.安装ph ...
- Jquery Validate 正则表达式实用验证代码
jQuery.validate 的正则验证功能,包括手机号码.电话号码.邮政编码.QQ号码.IP地址.字母和数字.中文的验证等. 手机号码验证 以下为引用内容: jQuery.validator.a ...
- Unity3d使用蓝牙(bluetooth)开发IOS点对点网络游戏
著作权声明:本文由http://www.cnblogs.com/icker 原创,欢迎转载分享.转载时请保留该声明和作者博客链接,谢谢! 最近使用Unity3d制作的IOS游戏需要加入联网对战功能功能 ...
- fastjson 的使用
json解析:[2]fastjson 使用 http://jingyan.baidu.com/article/c74d6000672e450f6b595d53.html 利用阿里的fastjson包对 ...