zoukankan      html  css  js  c++  java
  • 【BZOJ】1066: [SCOI2007]蜥蜴

    【算法】网络流-最大流(dinic)

    【题解】

    构图思路:

    因为石柱高度是可以被消耗的,即一根石柱可通过的蜥蜴数量有限,取舍问题中这样表示容量的属性显然可以作为网络流中的边

    于是将一根石柱拆成顶部和底部,中间连一条容量为石柱高度的边。

    超级源向有蜥蜴的石柱顶连一条容量为1的边(表示一只蜥蜴)。

    可以跳出地图的石柱底向超级汇连一条容量为inf的边。

    d距离内的两根石柱连一条容量为inf的边。

    记得结果要的是逃不掉的蜥蜴数。

    edge数组开大!!!

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1000,inf=0x3f3f3f3f;
    struct edge{int from,v,flow;}e[500000];
    int n,m,d,first[maxn],cur[maxn],q[510],p[30][30],dt[maxn],S=0,T=801,tot=1,ans=0;
    void insert(int u,int v,int w)
    {tot++;e[tot].v=v;e[tot].flow=w;e[tot].from=first[u];first[u]=tot;
     tot++;e[tot].v=u;e[tot].flow=0;e[tot].from=first[v];first[v]=tot;}
    bool bfs()
    {
        memset(dt,-1,sizeof(dt));
        int head=0,tail=1;q[0]=S;dt[S]=0;
        while(head!=tail)
         {
             int x=q[head++];if(head>=501)head=0;
             for(int i=first[x];i;i=e[i].from)
              if(dt[e[i].v]==-1&&e[i].flow>0)
               {
                   q[tail++]=e[i].v;if(tail>=501)tail=0;
                   dt[e[i].v]=dt[x]+1;
               }
         }
        if(dt[T]==-1)return 0;
        return 1;
    }
    int dinic(int x,int a)
    {
        if(x==T||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].from)
         if(dt[e[i].v]==dt[x]+1&&(f=dinic(e[i].v,min(a,e[i].flow)))>0)
          {
              e[i].flow-=f;
              e[i^1].flow+=f;//tot从2开始!建反向弧! 
              flow+=f;
              a-=f;
              if(a==0)break;
          }
        return flow;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&d);
        int cnt=0;
        char s[30];
        for(int i=1;i<=n;i++)
         {
             scanf("%s",s+1);
             for(int j=1;j<=m;j++)
              {
                  cnt++;int u;
                  p[i][j]=cnt;
                  u=s[j]-'0';
                  if(u)insert(cnt,cnt+400,u);
              }
         }
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          for(int x=max(i-d,1);x<=min(i+d,n);x++)
           for(int y=max(j-d,1);y<=min(j+d,m);y++)
            if((i!=x||j!=y)&&(i-x)*(i-x)+(j-y)*(j-y)<=(d*d))
             insert(p[i][j]+400,p[x][y],inf);
        for(int i=1;i<=n;i++)
         {
             scanf("%s",s+1);
             for(int j=1;j<=m;j++)
              if(s[j]=='L')insert(S,p[i][j],1),ans++;
         }
        for(int i=d+1;i<=n-d;i++)
         for(int j=1;j<=d;j++)
          {
              insert(p[i][j]+400,T,inf);
              insert(p[i][m-j+1]+400,T,inf);
          }
        for(int i=1;i<=d;i++)
         for(int j=1;j<=m;j++)
          {
              insert(p[i][j]+400,T,inf);
              insert(p[n-i+1][j]+400,T,inf);
          }
        while(bfs())
         {
             for(int i=0;i<=801;i++)cur[i]=first[i];
             ans-=dinic(S,inf);
         }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    docker file和容器数据卷,发布镜像
    Docker的镜像原理和分层理解和打包镜像
    docker部署nginx,tomcat 练习
    Docker 命令和运行原理简单剖析
    Docker安装
    Java垃圾回收-栈和堆部分知识
    aio-pika的使用
    技术基础 | 在Apache Cassandra中改变VNodes数量的影响
    行业动态 | 通过使用Apache Cassandra实现实时供应链管理
    行业动态 | Apache Pulsar 对现代数据堆栈至关重要的四个原因
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6431245.html
Copyright © 2011-2022 走看看