【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
5 8 2
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..
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=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } //*************************** namespace NetFlow { const int MAXN=100000,MAXM=500000,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=0; memset(G,-1,sizeof(G[0])*N); } void link(int u,int v,int c) { E[sz]=Edge(v,c,0,G[u]); G[u]=sz++; E[sz]=Edge(u,0,0,G[v]); G[v]=sz++; } int ISAP(int S,int T) { //S -> T int maxflow=0,aug=inf,flag=false,u,v; for (int i=0; i<N; ++i)cur[i]=G[i],gap[i]=dis[i]=0; 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]+1) { 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]^1].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]])==0) break; ++gap[dis[u]=mx+1]; u=pre[u]; } return maxflow; } bool bfs(int S,int T) { static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N); dis[S]=0; Q[0]=S; for (int h=0,t=1,u,v,it; h<t; ++h) { for (u=Q[h],it=G[u]; ~it; it=E[it].nx) { if (dis[v=E[it].v]==-1&&E[it].c>E[it].f) { dis[v]=dis[u]+1; Q[t++]=v; } } } return dis[T]!=-1; } int dfs(int u,int T,int low) { if (u==T) return low; int ret=0,tmp,v; for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx) { if (dis[v=E[it].v]==dis[u]+1&&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^1].f-=tmp; } } } if (!ret) dis[u]=-1; return ret; } int dinic(int S,int T) { int maxflow=0,tmp; while (bfs(S,T)) { memcpy(cur,G,sizeof(G[0])*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[33][33],mp2[33][33]; cin>>n>>m>>d; init(1500); for(int i=1; i<=n; i++) { scanf("%s",mp[i]+1); } for(int i=1; i<=n; i++) { scanf("%s",mp2[i]+1); } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if((mp[i][j]-'0')>0) { 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<0||k<0||h>n+1||k>m+1) continue; double dd=d*1.0; if(dist(i,j,h,k)>dd)continue; if(h==0||k==0||h==n+1||k==m+1) link((i-1)*m+j+400,1000,inf); else link((i-1)*m+j+400,(h-1)*m+k,inf); } } link((i-1)*m+j,(i-1)*m+j+400,mp[i][j]-'0'); } } } int sum=0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(mp2[i][j]=='L') { sum++; link(999,(i-1)*m+j,1); } } } cout<<sum-dinic(999,1000)<<endl; return 0; }
补:
#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+500, M = 1e3+20, mod = 1e9+7, inf = 2e9; char s[30]; int head[N],S,T,r,c,d,t=2,h[N],height[30][30],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,0);} bool bfs() { memset(h,-1,sizeof(h)); int l = 0, r = 1,now; q[l] = S; h[S] = 0; while(l!=r) { now=q[l++];if(l == 900) l=0; for(int i=head[now];i;i=e[i].next) { if(e[i].v&&h[e[i].to]==-1) { h[e[i].to] = h[now] + 1; q[r++]=e[i].to; if(r == 900) r = 0; } } } if(h[T] == -1) return 0; return 1; } int dfs(int x,int f) { if(x == T) return f; int used=0,w; for(int i=head[x];i;i=e[i].next) { if(e[i].v&&h[e[i].to] == h[x]+1) { w = dfs(e[i].to,min(f-used,e[i].v)); used+=w;e[i].v-=w;e[i^1].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=3*r*c,T=S+1; for(int i = 1; i <= r; ++i) { scanf("%s",s+1); for(int j = 1; j <= c; ++j) { height[i][j] = s[j]-'0'; add((i-1)*c+j,(i-1)*c+j+r*c,height[i][j]); if(i-d<=0||j-d<=0||i+d>r||j+d>c) { add((i-1)*c+j+r*c,T,inf); } } } int sum = 0; for(int i = 1; i <= r; ++i) { scanf("%s",s+1); for(int j = 1; j <= c; ++j) { if(s[j] == 'L') { sum++; add(S,(i-1)*c+j,1); } for(int k = 1; k <= r; ++k) for(int h = 1; h <= c; ++h) { if((k!=i||j!=h) && dis(i,j,k,h) <= 1.0*d) { add((i-1)*c+j+r*c,(k-1)*c+h,inf); } } } } dinic(); printf("%d\n",sum-ans); //cout<<sum-ans<<endl; return 0; }