【网络流】【BZOJ1006】【SCOI2007】蜥蜴

学弟@lher在周末训练赛中出的题目的原题(这个人拿省选题来当作提高组模拟,太丧了。。。)

题意简析:看题目:)

解题思路:题目显然是最大流。

首先拆点将点权变为边权,然后按照题意对于所有有跳板的点向可以跳到的点连一条权值为inf的边,对于能够跳出地图边界的点,将它与汇点连一条权值为inf的边。对于有蜥蜴的点,从源点向这个点连一条权值为1的边,然后跑一次最大流,答案就是蜥蜴数-最大流。

AC代码:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define ll long long
#define inf 0x7fffffff
using namespace std;
struct zxy{
    int next,to,v;
}edge[1000005];
int n,m,d,head[10005],iter[10005],lev[10005],que[100005],cnt=1,mz=0;
bool b[55][55];
inline int getno(int x,int y){ return (x-1)*m+y;}
inline int getdis(int x,int y,int a,int b){ return ceil(sqrt((x-a)*(x-a)+(y-b)*(y-b)));}
inline void ins(int x,int y,int l){edge[++cnt].next=head[x],head[x]=cnt,edge[cnt].to=y,edge[cnt].v=l;}
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline bool bfs(int s,int e){
    memset(lev,-1,sizeof(lev));
    int t=1,h=0;
    que[1]=s;
    lev[s]=0;
    do{
        h++;
        int k=head[que[h]];
        while(k){
            if (lev[edge[k].to]==-1&&edge[k].v){
                lev[edge[k].to]=lev[que[h]]+1;
                que[++t]=edge[k].to;
            }
            k=edge[k].next;
        }
    }while(h<t);
    return lev[e]!=-1;
}
inline int dfs(int u,int v,int f){
    if (u==v) return f;
    int used=0,k=head[u];
    while(k){
        if (edge[k].v&&lev[edge[k].to]==lev[u]+1){
            int w=dfs(edge[k].to,v,min(edge[k].v,f-used));
            used+=w;
            edge[k].v-=w;
            edge[k^1].v+=w;
            if (used==f) return used;
        }
        k=edge[k].next;
    }
    return used;
}
int dinic(int s,int t){
    int flow=0;
    while(bfs(s,t))
        flow+=dfs(s,t,inf);
    return flow;
}
void init(){
    n=in(),m=in(),d=in();
    for (int i=1; i<=n; ++i){
        for (int j=1; j<=m; ++j){
            int x=getchar()-'0',no=getno(i,j);
            if (x) ins(no,no+n*m,x),ins(no+n*m,no,0),b[i][j]=1;
        }
        getchar();
    }
    for (register int i=1; i<=n; ++i){
        for(register int j=1; j<=m; ++j)
            if (getchar()=='L') ++mz,ins(0,getno(i,j),1),ins(getno(i,j),0,0);
        getchar();
    }
    for (register int i=1; i<=n; ++i)
        for (register int j=1; j<=m; ++j)
        if(b[i][j]){
            if (i-d<1||i+d>n||j-d<1||j+d>m) ins(getno(i,j)+n*m,n*m*2+1,inf),ins(n*m*2+1,getno(i,j)+n*m,0);
            for (int k=(i-d<1?1:i-d); k<=(i+d>n?n:i+d); ++k)
                for (int t=(j-d<1?1:j-d); t<=(j+d>m?m:j+d); ++t)
                    if (b[k][t]&&getdis(i,j,k,t)<=d&&(i!=k||j!=t))
                        ins(getno(i,j)+n*m,getno(k,t),inf),ins(getno(k,t),getno(i,j)+n*m,0);
        }
}
int main(){
    init();
    printf("%d",mz-dinic(0,2*n*m+1));
    return 0;
}

 本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

posted @ 2017-03-18 21:08  Melacau  阅读(254)  评论(1编辑  收藏  举报