BZOJ 1066[SCOI2007]蜥蜴
学了ISAP说我来做一道网络流的傻逼题吧然后自己变成了一个傻逼。。
De了很久的bug然后发现我从源点向每只蜥蜴连了INF的边,喵喵喵?
最近写博客好像比较敷衍,还是说一下。每个柱子拆点,源点向每个有蜥蜴的真点连1的边,每个真点向假点连石柱高的边,每个假点向它能到达的柱子的真点连INF的边,每个能跳出去的柱子向汇点连INF的边。
跑得比Dinic慢。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
using namespace std;
const int maxn=20000+25;
const int INF=0x7fffffff;
int tot,r,c,D,s,t,n,d[maxn],fir[maxn],cur[maxn],cnt[maxn],p[maxn],a[maxn],is[maxn],ecnt=1;
char ss[50][50];
struct edge {
int from,to,cap,flow,nxt;
edge(){}
edge(int from,int to,int cap,int flow,int nxt):from(from),to(to),cap(cap),flow(flow),nxt(nxt){}
}e[maxn*2];
void add(int u,int v,int w) {
e[++ecnt]=edge(u,v,w,0,fir[u]);
e[++ecnt]=edge(v,u,0,0,fir[v]);
fir[u]=ecnt-1; fir[v]=ecnt;
}
queue<int>que;
void bfs() {
for(int i=1;i<=n;i++) d[i]=n;
d[t]=0; que.push(t);
while(!que.empty()) {
int x=que.front(); que.pop();
for(int i=fir[x];i;i=e[i].nxt)
if(d[e[i].to]==n&&e[i].flow==e[i].cap) {
d[e[i].to]=d[x]+1;
que.push(e[i].to);
}
}
}
int cal() {
int res=INF;
for(int x=t;x!=s;x=e[p[x]].from)
res=min(res,e[p[x]].cap-e[p[x]].flow);
for(int x=t;x!=s;x=e[p[x]].from) {
e[p[x]].flow+=res;
e[p[x]^1].flow-=res;
}
return res;
}
int Maxflow() {
bfs();
for(int i=1;i<=n;i++) cur[i]=fir[i],cnt[d[i]]++;
int res=0;
for(int x=s;d[x]<n;) {
if(x==t) {
res+=cal();
x=s;
}
int ok=0;
for(int &i=cur[x];i;i=e[i].nxt)
if(d[e[i].to]+1==d[x]&&e[i].flow<e[i].cap){
p[x=e[i].to]=i;ok=1;break;
}
if(!ok) {
cur[x]=fir[x]; int M=n;
for(int i=fir[x];i;i=e[i].nxt)
if(e[i].cap>e[i].flow){M=min(M,d[e[i].to]+1);}
if(!(--cnt[d[x]])) break;
cnt[d[x]=M]++;
if(x!=s) x=e[p[x]].from;
}
}
return res;
}
double dis(int x,int y,int xx,int yy) {return sqrt((double)(x-xx)*(x-xx)+(double)(y-yy)*(y-yy));}
void ADD(int x,int y) {
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
if(i==x&&j==y) continue;
else if(dis(x,y,i,j)<=(double)D) add(r*c+(x-1)*c+y,(i-1)*c+j,INF);
add((x-1)*c+y,r*c+(x-1)*c+y,a[(x-1)*c+y]);
if(min(x,r-x+1)<=D||min(y,c-y+1)<=D) add(r*c+(x-1)*c+y,t,INF);
}
void init() {
scanf("%d%d%d",&r,&c,&D);
s=r*c*2+1; t=r*c*2+2; n=t;
for(int i=1;i<=r;i++) {
for(int j=1;j<=c;j++) {
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
a[(i-1)*c+j]=ch-'0';
}
}
for(int i=1;i<=r;i++) {
for(int j=1;j<=c;j++) {
char ch=getchar();
while(ch!='.'&&ch!='L') ch=getchar();
if(ch=='L') {tot++; add(s,(i-1)*c+j,1);}
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
ADD(i,j);
}
void work() {
printf("%d\n",tot-Maxflow());
}
int main()
{
init();
work();
return 0;
}