BZOJ1066[SCOI2007]蜥蜴
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1066
感觉比较水的一道题。
发现蜥蜴可以随便跳,然后柱子的高度对于能不能跳到并没有什么用,所以高度就是相当于每个柱子只允许hi只蜥蜴跳过它。
所以高度就是这个柱子的限制次数,这不就是拆点后连hi的限制边,然后随便跑一个最大流就可以了么?...
但是这题我SB开小了多次数组= =,你们知道这样建图最多有多少条边吗?...应该是n*m*d*d=400*16=6400吧?如果考虑拆点似乎只是+n*m?
然后发现我开这么多也不能过,难道是因为源点和汇点的影响吗?...其实做完才发现,其实一个点最多可以连出去(2*d)^2*pi条边,所以是n*m*(2*d)*(2*d)=25600条边;然后一条双向边要*2,所以开51200是最好的咯?...
反正我当时没想清,发现RE+TLE几次,于是索性就开了100000过了,而且因为是拆点,所以点的个数也要翻一倍,不要忘了。
唔,又复习一遍dinic,感觉模板终于不会打错了。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=22; const int maxt=810; const int INF=0x3f3f3f3f; struct Node{ int data,next,low; }node[100010]; #define now node[point].data #define then node[point].next #define www node[point].low int n,m,d,Idex,cnt; int s,t,tot; int head[maxt],cur[maxt]; int dis[maxt],que[maxt]; int ind[maxn][maxn]; char m1[maxn][maxn],m2[maxn][maxn]; void add(int u,int v,int w){ node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;head[u]=cnt++; node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=0;head[v]=cnt++; } void init(int x,int y){ if(x-d<=0 || y-d<=0 || x+d>n || y+d>m) add(ind[x][y]+Idex,t,INF); for(int i=max(1,x-d);i<=min(n,x+d);i++) for(int j=max(1,y-d);j<=min(m,y+d);j++) if(m1[i][j]>'0') if(abs(i-x)+abs(j-y)<=d) add(ind[x][y]+Idex,ind[i][j],INF); } bool BFS(){ memset(dis,-1,sizeof(dis)); int H=0,T=1;que[1]=s,dis[s]=0; while(H<T){ H++; for(int point=head[que[H]];point!=-1;point=then) if(www && dis[now]<0){ dis[now]=dis[que[H]]+1; que[++T]=now; } } if(dis[t]<0) return false; return true; } int dfs(int x,int low){ if(x==t) return low; int Low; for(int &point=cur[x];point!=-1;point=then) if(www && dis[now]==dis[x]+1){ Low=dfs(now,min(low,www)); if(Low){ www-=Low;node[point^1].low+=Low; return Low; } } return 0; } int main(){ #ifndef ONLINE_JUDGE freopen("1066.in","r",stdin); freopen("1066.out","w",stdout); #endif scanf("%d%d%d",&n,&m,&d); for(int i=1;i<=n;i++) scanf("%s",m1[i]+1); for(int i=1;i<=n;i++) scanf("%s",m2[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(m1[i][j]>'0') ind[i][j]=++Idex; t=(Idex<<1)+1; for(int i=s;i<=t;i++) head[i]=-1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(m1[i][j]>'0'){ add(ind[i][j],ind[i][j]+Idex,m1[i][j]-'0'); init(i,j); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(m2[i][j]=='L') add(s,ind[i][j],1),tot++; int flag,sum=0; while(BFS()){ for(int i=s;i<=t;i++) cur[i]=head[i]; while(1){ flag=dfs(s,INF); if(!flag) break; sum+=flag; } } printf("%d",tot-sum); return 0; }