bzoj 1066 蜥蜴
最大流。
建图:首先将每根柱子拆成两个点。
每根柱子的入点向出点连一条容量为柱子高度的边。
每根柱子的出点向可以到达的柱子的入点连一条容量为正无穷的边。
源点向每根初始有蜥蜴的柱子的入点连一条容量为一的边。
每根可以跳出地图的柱子的出点向汇点连一条容量为正无穷的边。
跑一遍最大流就是最多能逃出的蜥蜴数。
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int dian=8005; 9 const int bian=160005; 10 const int INF=0x3f3f3f3f; 11 int h[dian],nxt[bian],ver[bian],val[bian],ch[dian]; 12 char mapp[25][25],map[25][25]; 13 char lala[25]; 14 int n,m,d,tot,ans; 15 int S,T; 16 void add(int aa,int bb,int cc){ 17 tot++;ver[tot]=bb;nxt[tot]=h[aa];val[tot]=cc;h[aa]=tot; 18 tot++;ver[tot]=aa;nxt[tot]=h[bb];val[tot]=0;h[bb]=tot; 19 } 20 int bh(int aa,int bb,int cc){ 21 return (aa-1)*m+bb+cc*n*m; 22 } 23 bool tell(){ 24 memset(ch,-1,sizeof(ch)); 25 queue<int>q; 26 q.push(S); 27 ch[S]=0; 28 while(!q.empty()){ 29 int t=q.front(); 30 q.pop(); 31 for(int i=h[t];i;i=nxt[i]) 32 if(ch[ver[i]]==-1&&val[i]){ 33 q.push(ver[i]); 34 ch[ver[i]]=ch[t]+1; 35 } 36 } 37 return ch[T]!=-1; 38 } 39 int zeng(int a,int b){ 40 if(a==T) 41 return b; 42 int r=0; 43 for(int i=h[a];i&&b>r;i=nxt[i]) 44 if(ch[a]+1==ch[ver[i]]&&val[i]){ 45 int t=zeng(ver[i],min(b-r,val[i])); 46 val[i]-=t,r+=t,val[i^1]+=t; 47 } 48 if(!r) 49 ch[a]=-1; 50 return r; 51 } 52 int dinic(){ 53 int r=0,t; 54 while(tell()) 55 while(t=zeng(S,INF)) 56 r+=t; 57 return r; 58 } 59 int main(){ 60 tot=1; 61 scanf("%d%d%d",&n,&m,&d); 62 S=2*n*m+1,T=2*n*m+2; 63 for(int i=1;i<=n;i++) 64 scanf("%s",mapp[i]+1); 65 for(int i=1;i<=n;i++) 66 for(int j=1;j<=m;j++) 67 map[i][j]=mapp[i][j]-'0'; 68 for(int i=1;i<=n;i++) 69 for(int j=1;j<=m;j++) 70 if(map[i][j]){ 71 add(bh(i,j,0),bh(i,j,1),map[i][j]); 72 for(int k=i-d;k<=i+d;k++) 73 for(int l=j-d;l<=j+d;l++) 74 if(k>=1&&k<=n&&l>=1&&l<=m&&(k!=i||l!=j)&&abs(k-i)*abs(k-i)+abs(l-j)*abs(l-j)<=d*d&&map[k][l]) 75 add(bh(i,j,1),bh(k,l,0),INF); 76 } 77 for(int i=1;i<=n;i++) 78 for(int j=1;j<=m;j++) 79 if(min(min(i,n+1-i),min(j,m+1-j))<=d&&map[i][j]) 80 add(bh(i,j,1),T,INF); 81 for(int i=1;i<=n;i++){ 82 scanf("%s",lala+1); 83 for(int j=1;j<=m;j++) 84 if(lala[j]=='L'){ 85 ans++; 86 add(S,bh(i,j,0),1); 87 } 88 } 89 printf("%d",ans-dinic()); 90 return 0; 91 }
注意:
数组大小要好好算。
读入均为字符串形式。
距离为欧几里得距离。