zoukankan      html  css  js  c++  java
  • bzoj1066 蜥蜴 (dinic)

    最大流板子题。

    对于每根柱子,建两个点ai,bi,建边(ai,bi,柱子高度)

    对于距离不超过d的两根柱子i,j,建边(bi,aj,inf)

    对于起始位置在i的每个蜥蜴,建边(S,ai,1)

    对于能跳出地图的柱子i,建边(bi,E,inf)

    然后跑dinic即可

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=23,inf=0x3f3f3f3f;
    
    struct Edge{
        int a,b,v;
        int ne;
    }eg[maxn*maxn*maxn*maxn*4];
    
    int R,C,D,pcnt,rcnt,ecnt;
    int map[maxn][maxn][2];
    int rd[100][2];
    int egh[maxn*maxn*2],P[maxn][maxn][2];
    int deep[maxn*maxn*2];
    
    inline void addedge(int a,int b,int v){
        eg[ecnt].a=a;eg[ecnt].b=b;eg[ecnt].v=v;eg[ecnt].ne=egh[a];egh[a]=ecnt++;
        eg[ecnt].a=b;eg[ecnt].b=a;eg[ecnt].v=0;eg[ecnt].ne=egh[b];egh[b]=ecnt++;
    }
    
    bool bfs(){
        queue<int> q;memset(deep,0,sizeof(deep));
        q.push(1);deep[1]=1;
        while(!q.empty()){
            int p=q.front();q.pop();
            for(int i=egh[p];i!=-1;i=eg[i].ne){
                if(eg[i].v&&!deep[eg[i].b]){
                    q.push(eg[i].b);deep[eg[i].b]=deep[p]+1;
                }
            }
        }return deep[2];
    }
    
    int dinic(int x,int l){
        if(x==2)  return l;int tmp=l;
        for(int i=egh[x];i!=-1;i=eg[i].ne){
            if(deep[eg[i].b]!=deep[x]+1||!eg[i].v)  continue;
            int re=dinic(eg[i].b,min(eg[i].v,l));
            if(!re) deep[eg[i].b]=0;
            tmp-=re;eg[i].v-=re;eg[i^1].v+=re;
            if(!tmp)  break;
        }return l-tmp;
    }
    
    int main(){
        int i,j,k,ans=0;
        char s[maxn];
        //freopen("1066.in","r",stdin);
        scanf("%d%d%d",&R,&C,&D);
        for(i=1;i<=R;i++){
            scanf("%s",s+1);
            for(j=1;j<=C;j++)  map[i][j][0]=s[j]-'0';
        }
        for(i=1;i<=R;i++){
            scanf("%s",s+1);
            for(j=1;j<=C;j++)  map[i][j][1]=(s[j]=='L'?1:0);
        }
        for(i=-D;i<=D;i++){
            for(j=-D;j<=D;j++){
                if(i*i+j*j<=D*D){rd[rcnt][0]=i;rd[rcnt++][1]=j;}
            }
        }
        pcnt=2;memset(egh,-1,sizeof(egh));
        for(i=1;i<=R;i++)  for(j=1;j<=C;j++)  if(map[i][j][0]){
            P[i][j][0]=++pcnt;P[i][j][1]=++pcnt;addedge(P[i][j][0],P[i][j][1],map[i][j][0]);
            if(map[i][j][1])  {addedge(1,P[i][j][0],1);ans++;}
            }
        for(i=1;i<=R;i++){
            for(j=1;j<=C;j++){
                if(!map[i][j][0])  continue;
                bool b=0;
                for(k=0;k<rcnt;k++){
                    int ii=i+rd[k][0],jj=j+rd[k][1];
                    if(ii<=0||ii>R||jj<=0||jj>C)  b=1;
                    else if(map[ii][jj])  addedge(P[i][j][1],P[ii][jj][0],inf);
                }if(b)  addedge(P[i][j][1],2,inf);
            }
        }
        while(bfs())  ans-=dinic(1,inf);
        printf("%d",ans);
    }
  • 相关阅读:
    【Redis】集群NetCore实战
    【Redis】集群教程(Windows)
    【Redis】入门
    【SQL SERVER】索引
    【SQL SERVER】锁机制
    【SQL SERVER】数据内部存储结构简单探索
    Windows软件包管理工具
    Git常用命令记录
    【ASP.NET Core学习】远程过程调用
    CouchDB学习-API
  • 原文地址:https://www.cnblogs.com/Ressed/p/9354379.html
Copyright © 2011-2022 走看看