[BZOJ1066]SCOI2007蜥蜴|最大流

来源:互联网 发布:我的世界服务器开挂js 编辑:程序博客网 时间:2024/05/16 01:39

挺显然的最大流,源向所有有蜥蜴的点连inf边,所有点拆成入点和出点,入店向出点连流量为高度的边,限制流量,所有可以一步跳出去的点向汇连inf边,跑最大流就行了。。

#include<iostream>#include<cstdio>#include<memory.h>#define inf 99999999#define maxn 1005using namespace std;struct edge{int e,f,next;} ed[500005];int i,j,r,c,dm,n,nd,ne=0,cnt=0,a[maxn],map[25][25],dui[500005],d[maxn],u[maxn],que[maxn];char ch;void add(int s,int e,int f){ed[++ne].e=e;ed[ne].f=f;ed[ne].next=a[s];a[s]=ne;dui[ne]=ne+1;dui[ne+1]=ne;ed[++ne].e=s;ed[ne].f=0;ed[ne].next=a[e];a[e]=ne;}void make(int x,int y,int k){int t=(x-1)*c+y,i,j;add(t,t+n,map[x][y]);if (k) add(0,t,1);if (x<=dm||x+dm>r||y<=dm||y+dm>c) add(t+n,nd,inf);for (i=1;i<=r;i++)for (j=1;j<=c;j++)if (map[i][j]&&dm*dm>=(x-i)*(x-i)+(y-j)*(y-j)) add(t+n,(i-1)*c+j,inf);}bool bfs(int s,int t){int head=1,tail=1,get,j;memset(d,0,sizeof(d));memset(u,0,sizeof(u));u[s]=1;que[1]=s;while (head<=tail){get=que[head];for (j=a[get];j;j=ed[j].next)if (!u[ed[j].e]&&ed[j].f) {u[ed[j].e]=1;d[ed[j].e]=d[get]+1;que[++tail]=ed[j].e;}head++;}return d[t]!=0;}int extend(int x,int minf,int t){if (x==t) return minf;int f=minf,j,del;for (j=a[x];j;j=ed[j].next)if (d[ed[j].e]==d[x]+1&&ed[j].f){del=extend(ed[j].e,min(minf,ed[j].f),t);ed[j].f-=del;ed[dui[j]].f+=del;minf-=del;if (!minf) break;}if (f==minf) d[x]=0;return f-minf;}int dinic(int s,int t){int ans=0;while (bfs(s,t)) ans+=extend(s,inf,t);return ans;}int main(){freopen("1066.in","r",stdin);scanf("%d%d%d\n",&r,&c,&dm);n=r*c;nd=2*n+1;for (i=1;i<=r;i++){for (j=1;j<=c;j++){scanf("%c",&ch);map[i][j]=ch-'0';}scanf("\n");}for (i=1;i<=r;i++){for (j=1;j<=c;j++){scanf("%c",&ch);if (ch=='L') cnt++;if (map[i][j]) make(i,j,ch=='L');}scanf("\n");}cout<<cnt-dinic(0,nd);} 


0 0