【bzoj1066】[SCOI2007]蜥蜴 网络最大流

时间:2023-03-08 20:26:38

【bzoj1066】[SCOI2007]蜥蜴

Description

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

Input

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

Output

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

Sample Input

5 8 2
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..

Sample Output

1

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