bzoj1066 蜥蜴 (dinic)

时间:2021-05-26 05:41:33

最大流板子题。

对于每根柱子,建两个点ai,bi,建边(ai,bi,柱子高度)

对于距离不超过d的两根柱子i,j,建边(bi,aj,inf)

对于起始位置在i的每个蜥蜴,建边(S,ai,1)

对于能跳出地图的柱子i,建边(bi,E,inf)

然后跑dinic即可

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=,inf=0x3f3f3f3f; struct Edge{
int a,b,v;
int ne;
}eg[maxn*maxn*maxn*maxn*]; int R,C,D,pcnt,rcnt,ecnt;
int map[maxn][maxn][];
int rd[][];
int egh[maxn*maxn*],P[maxn][maxn][];
int deep[maxn*maxn*]; inline void addedge(int a,int b,int v){
eg[ecnt].a=a;eg[ecnt].b=b;eg[ecnt].v=v;eg[ecnt].ne=egh[a];egh[a]=ecnt++;
eg[ecnt].a=b;eg[ecnt].b=a;eg[ecnt].v=;eg[ecnt].ne=egh[b];egh[b]=ecnt++;
} bool bfs(){
queue<int> q;memset(deep,,sizeof(deep));
q.push();deep[]=;
while(!q.empty()){
int p=q.front();q.pop();
for(int i=egh[p];i!=-;i=eg[i].ne){
if(eg[i].v&&!deep[eg[i].b]){
q.push(eg[i].b);deep[eg[i].b]=deep[p]+;
}
}
}return deep[];
} int dinic(int x,int l){
if(x==) return l;int tmp=l;
for(int i=egh[x];i!=-;i=eg[i].ne){
if(deep[eg[i].b]!=deep[x]+||!eg[i].v) continue;
int re=dinic(eg[i].b,min(eg[i].v,l));
if(!re) deep[eg[i].b]=;
tmp-=re;eg[i].v-=re;eg[i^].v+=re;
if(!tmp) break;
}return l-tmp;
} int main(){
int i,j,k,ans=;
char s[maxn];
//freopen("1066.in","r",stdin);
scanf("%d%d%d",&R,&C,&D);
for(i=;i<=R;i++){
scanf("%s",s+);
for(j=;j<=C;j++) map[i][j][]=s[j]-'';
}
for(i=;i<=R;i++){
scanf("%s",s+);
for(j=;j<=C;j++) map[i][j][]=(s[j]=='L'?:);
}
for(i=-D;i<=D;i++){
for(j=-D;j<=D;j++){
if(i*i+j*j<=D*D){rd[rcnt][]=i;rd[rcnt++][]=j;}
}
}
pcnt=;memset(egh,-,sizeof(egh));
for(i=;i<=R;i++) for(j=;j<=C;j++) if(map[i][j][]){
P[i][j][]=++pcnt;P[i][j][]=++pcnt;addedge(P[i][j][],P[i][j][],map[i][j][]);
if(map[i][j][]) {addedge(,P[i][j][],);ans++;}
}
for(i=;i<=R;i++){
for(j=;j<=C;j++){
if(!map[i][j][]) continue;
bool b=;
for(k=;k<rcnt;k++){
int ii=i+rd[k][],jj=j+rd[k][];
if(ii<=||ii>R||jj<=||jj>C) b=;
else if(map[ii][jj]) addedge(P[i][j][],P[ii][jj][],inf);
}if(b) addedge(P[i][j][],,inf);
}
}
while(bfs()) ans-=dinic(,inf);
printf("%d",ans);
}