BZOJ1066 [SCOI2007] 蜥蜴(Dinic算法求最大流)
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃 到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石 柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不 变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个 石柱上。
Input
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱 ,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
Output
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; const int inf=1e9; int r,c,d; //链式前向星存图 int head[maxn]; int tol=0; struct node { int u; int v; int w; int next; }edge[maxn]; void addedge (int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol].w=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].u=v; edge[tol].v=u; edge[tol].w=0; edge[tol].next=head[v]; head[v]=tol++; } //Dinic算法求最大流 int dep[maxn]; int inque[maxn]; int vi; int cur[maxn]; int maxflow=0; int s,t; bool bfs () { for (int i=0;i<=t;i++) cur[i]=head[i],dep[i]=inf,inque[i]=0; dep[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int u=q.front(); q.pop(); inque[u]=0; for (int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inque[v]==0) { q.push(v); inque[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { vi=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].next) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { while (bfs()) { vi=1; while (vi==1) { vi=0; dfs(s,inf); } } return maxflow; } int g[1050][1050]; int pos (int x,int y,int f) { return (x-1)*c+y+r*c*f; } double getDis (int x1,int y1,int x2,int y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } int judge (int x,int y) { return x<=d||r-x<d||y<=d||c-y<d; } int main(){ scanf("%d%d%d",&r,&c,&d); memset(head,-1,sizeof(head)); s=0;t=2*r*c+1; char s1[maxn]; for (int i=1;i<=r;i++){ scanf("%s",s1+1); for(int j=1;j<=c;j++) g[i][j]=s1[j]-'0'; } int num=0; for(int i=1;i<=r;i++){ scanf("%s",s1+1); for(int j=1;j<=c;j++){ if(s1[j]=='L') num++,addedge(s,pos(i,j,0),1); } } for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ if(g[i][j]){ addedge(pos(i,j,0),pos(i,j,1),g[i][j]); } } } for(int x1=1;x1<=r;x1++){ for(int y1=1;y1<=c;y1++){ if(!g[x1][y1]) continue; for(int x2=1;x2<=r;x2++){ for(int y2=1;y2<=c;y2++){ if (x1==x2&&y1==y2) continue; if (g[x2][y2]&&getDis(x1,y1,x2,y2)<=d){ addedge(pos(x1,y1,1),pos(x2,y2,0),inf); addedge(pos(x2,y2,1),pos(x1,y1,0),inf); } } } } } for(int i=1;i<=r;i++){ for(int j=1;j<=c;j++){ if(judge(i,j)){ addedge(pos(i,j,1),t,inf); } } } printf("%d",num-Dinic()); return 0; }