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;
}
View Code

 

posted @ 2016-02-25 09:01  诚叙  阅读(244)  评论(0编辑  收藏  举报