P2472 [SCOI2007]蜥蜴

主要问题是每个石柱能站的次数有限,那石柱就对应一条边,走 \(a\) 次对应流量为 \(a\)

#include<bits/stdc++.h>
using namespace std;
#define rg register
inline int read(){
    rg char ch=getchar();
    rg int x=0,f=0;
    while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
int r,c,d,s,t,ans,cnt,xx,yy;
char mp[25][25];
char g[25][25];
int vis[25][25];
int flag;
int head[810],ver[200010],nxt[200010],flow[200010],tot=1;
int dis[810],hh[820];
int dx[]={0,0,-1,1},dy[]={1,-1,0,0};
const int inf=99999999;
int bfs(){
    for(int i=s;i<=t;++i) hh[i]=head[i];
    memset(dis,0,sizeof dis);
    dis[s]=1;
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int y,i=head[x];i;i=nxt[i]){
            y=ver[i];
            if(!dis[y]&&flow[i]){
                dis[y]=dis[x]+1;
                q.push(y);
            }
        }
    }
    return dis[t]?true:false;
}
int dfs(int x,int f){
    if(x==t||!f) return f;
    int used = 0;
    for(int &i=hh[x];i;i=nxt[i]){
        int y=ver[i];
        if(dis[y]!=dis[x]+1||!flow[i]) continue;
        int w=dfs(y,min(f-used,flow[i]));
        if(w){
            flow[i]-=w;
            flow[i^1]+=w;
            used+=w;
            if(used==f) return f;
        }
    }
    if(!used) dis[x]=0;
    return used;
}
void dinic(){
    while(bfs()) ans+=dfs(s,inf);
}
int _dis(int x,int y,int xl,int yl){
	return (x-xl)*(x-xl)+(y-yl)*(y-yl);
}
inline void add(int x,int y,int z){
    ver[++tot]=y;
    flow[tot]=z;
    nxt[tot]=head[x];
    head[x]=tot;
}
void work(int x,int y,int now){
	if(_dis(x,y,xx,yy)>d*d) return;
    if(x<1||y<1||x>r||y>c){flag=1;return;}
    if(mp[x][y]!='0'){
        add(now,(x-1)*c+y,inf);
        add((x-1)*c+y,now,0);
    }
    vis[x][y]=1;
    for(int xl,yl,i=0;i<4;++i){
        xl=x+dx[i];yl=y+dy[i];
        if(!vis[xl][yl]) work(xl,yl,now);
    }
}
int main(){
    r=read(),c=read(),d=read();
    s=0;t=(c*r<<1)+1;
    for(int i=1;i<=r;++i) scanf("%s",mp[i]+1);
    for(int i=1;i<=r;++i) scanf("%s",g[i]+1);
    for(int i=1;i<=r;++i){
        for(int j=1;j<=c;++j){
            if(mp[i][j]=='0') continue;
            memset(vis,0,sizeof vis);
            flag=0;
            vis[i][j]=1;
            xx=i,yy=j;
            work(i,j,(i-1)*c+j+c*r);
            if(flag) add((i-1)*c+j+r*c,t,inf),add(t,(i-1)*c+j+r*c,0);
        }
    }
    for(int i=1;i<=r;++i){
        for(int j=1;j<=c;++j){
            if(g[i][j]=='L'){
                ++cnt;
                add(s,(i-1)*c+j,1);
                add((i-1)*c+j,s,0);
            }
        }
    }
    for(int i=1;i<=r;++i){
        for(int j=1;j<=c;++j){
            if(mp[i][j]!='0'){
                add((i-1)*c+j,(i-1)*c+j+c*r,mp[i][j]-'0');
                add((i-1)*c+j+c*r,(i-1)*c+j,0);
            }
        }
    }
    dinic();
    //cout<<ans<<endl;
    cout<<cnt-ans<<endl;
    return 0;
}
posted @ 2020-06-12 19:49  __int256  阅读(109)  评论(0编辑  收藏  举报