您的位置:首页 > 其它

[最大流]BZOJ 1066——[SCOI2007]蜥蜴

2017-07-02 19:05 369 查看

1066: [SCOI2007]蜥蜴

题目描述

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

解题思路

比较裸的网络流,每个节点有高度可以把点拆掉新建容量为高度的边权,建超级源连接所有L节点,容量为1,建超级汇连接所有可以跳出边界的节点,其容量和互相到达的节点之间建的容量都为无限大,然后直接刷Dinic就可以了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxv=805,maxm=1000005,MAXINT=2147483647;
int n,m,d,tot,lnk[maxv],que[maxv],sum,hed,til,dis[maxv],s,t,B[maxv];
int cap[maxm],flw[maxm],son[maxm],nxt[maxm];
bool vis[maxv];
inline char _read(){
char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='.'&&ch!='L') ch=getchar();
return ch;
}
int sqr(int x){return x*x;}
int getid(int i,int j,int k){return ((i-1)*m+j-1)*2+k;}
int getl(int x1,int y1,int x2,int y2){return sqr(x1-x2)+sqr(y1-y2);}
void add(int x,int y,int z){
nxt[tot]=lnk[x];lnk[x]=tot;son[tot]=y;cap[tot]=z;tot++;
nxt[tot]=lnk[y];lnk[y]=tot;son[tot]=x;cap[tot]=0;tot++;
}
void maker(){
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (_read()=='L') add(s,getid(i,j,1),1),sum++;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (i<=d||j<=d||(n-i+1)<=d||(m-j+1)<=d) add(getid(i,j,2),t,maxv);
for (int i1=1;i1<=n;i1++)
for (int j1=1;j1<=m;j1++)
for (int i2=1;i2<=n;i2++)
for (int j2=1;j2<=m;j2++)
if ((i1!=i2||j1!=j2)&&getl(i1,j1,i2,j2)<=sqr(d)) add(getid(i1,j1,2),getid(i2,j2,1),maxv);
}
bool BFS(){
memset(vis,0,sizeof(vis));
memset(dis,63,sizeof(dis));
hed=0,til=1;que[1]=s;vis[s]=1;dis[s]=1;
while (hed!=til){
int x=que[++hed];
for (int j=lnk[x];j!=-1;j=nxt[j])
if (!vis[son[j]]&&cap[j]>flw[j]){
dis[son[j]]=dis[x]+1;
vis[son[j]]=1;que[++til]=son[j];
}
}
return vis[t];
}
int DFS(int x,int mi){
if (x==t||!mi) return mi;
int num=0;
for (int &j=B[x];j!=-1;j=nxt[j])
if (dis[x]+1==dis[son[j]]){
int now=DFS(son[j],min(mi,cap[j]-flw[j]));
if (now){
flw[j]+=now;flw[j^1]-=now;
num+=now;mi-=now;
if (!mi) break;
}
}
return num;
}
void Dinic(){
int ans=0;
while (BFS()){
memcpy(B,lnk,sizeof(B));
ans+=DFS(s,MAXINT);
}
printf("%d\n",sum-ans);
}
int main(){
freopen("exam.in","r",stdin);
freopen("exam.out","w",stdout);
memset(lnk,255,sizeof(lnk));
scanf("%d%d%d",&n,&m,&d);
s=0,t=2*n*m+1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) add(getid(i,j,1),getid(i,j,2),_read()-48);
maker();
Dinic();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: