zoukankan      html  css  js  c++  java
  • P2472 [SCOI2007]蜥蜴(网络流)

    P2472 [SCOI2007]蜥蜴

    把每个点拆成2个点,两点之间连边的边权为石柱高度

    新建虚拟源点$S$和汇点$T$

    $S$向所有有蜥蜴的点连边,边权1

    其他边都连$inf$

    剩下就是裸的$dinic$辣

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define N 200005
    inline int Min(int a,int b){return a<b?a:b;}
    inline int Abs(int a){return a<0?-a:a;}
    const int inf=1e8;
    char a[25][25];
    int R,C,D,S,T,d[N],cur[N],tot; bool vis[N];
    int cnt=1,hd[N],nxt[N],ed[N],poi[N],val[N];
    queue <int> h;
    inline void adde(int x,int y,int v){
        nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt,
        ed[x]=cnt, poi[cnt]=y, val[cnt]=v;
    }
    inline void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);}
    inline int id(int x,int y){return (x-1)*C+y;}
    bool Bfs(){
        memset(vis,0,sizeof(vis));
        h.push(S); vis[S]=1;
        while(!h.empty()){
            int x=h.front(); h.pop();
            for(int i=hd[x];i;i=nxt[i]){
                int to=poi[i];
                if(!vis[to]&&val[i]>0)
                    vis[to]=1,d[to]=d[x]+1,h.push(to);
            }
        }return vis[T];
    }
    int Dfs(int x,int a){
        if(x==T||a==0) return a; 
        int F=0,f;
        for(int &i=cur[x];i&&a;i=nxt[i]){
            int to=poi[i];
            if(d[to]==d[x]+1&&(f=(Dfs(to,Min(a,val[i]))))>0)
                F+=f,a-=f,val[i]-=f,val[i^1]+=f;
        }return F;
    }
    int dinic(){
        int re=0;
        while(Bfs()){
            for(int i=1;i<=T;++i) cur[i]=hd[i];
            re+=Dfs(S,inf);
        }return re;
    }
    void draw(int x,int y){//向周围距离<=d的点连边
        if(a[x][y]=='0') return ;
        int p=id(x,y); bool tt=1;
        link(p<<1,p<<1|1,a[x][y]-'0');
        for(int i=x-D;i<=x+D;++i)
            for(int j=y-D;j<=y+D;++j){
                if((i==x&&j==y)||Abs(x-i)+Abs(y-j)>D) continue;
                if(i>0&&i<=R&&j>0&&j<=C) link(p<<1|1,id(i,j)<<1,inf);
                else if(tt) link(p<<1|1,T,inf),tt=0;
            }
    }
    int main(){
        scanf("%d%d%d",&R,&C,&D);
        S=R*C*2+2; T=S+1;
        for(int i=1;i<=R;++i) scanf("%s",a[i]+1);
        for(int i=1;i<=R;++i)
            for(int j=1;j<=C;++j)
                draw(i,j);
        for(int i=1;i<=R;++i) scanf("%s",a[i]+1);
        for(int i=1;i<=R;++i)
            for(int j=1;j<=C;++j)
                if(a[i][j]=='L')
                    link(S,id(i,j)<<1,1),++tot;
        printf("%d",tot-dinic());
        return 0;
    }
  • 相关阅读:
    MySQL索引长度限制问题
    Mysql查询缓存碎片、缓存命中率及Nagios监控
    PHP多台服务器跨域SESSION共享
    php会话全揭秘
    深入PHP中慎用双等于(==)的详解
    php二进制安全的含义
    分表,分库算法
    php学习网站推荐
    在linux平台下,设置core dump文件属性(位置,大小,文件名等)
    常用Linux shell命令汇总
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10765901.html
Copyright © 2011-2022 走看看