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
  • 相关阅读:
    SQL中文转拼音
    cocos2D 虚拟摇杆Joystick功能实现
    cocos2d 粒子效果以及Particle Designer粒子工具的学习
    android 模拟器出错,emulator: ERROR: unknown virtual device name
    [转][越狱破解] 苹果itouch 4 iOS5.0.1完美越狱教程+资源下载
    objectivec 中随机数的用法 (3种:arc4random() 、random()、CCRANDOM_0_1() )
    [转]cocos2dx添加广告条(IOS and Android)
    cocos2d1.0.1x0.10.0版本 设置横屏与竖屏的方法
    【转】总结阐述Cocos2dX与Cocos2diphone区别;
    Objectivec 中CGGeometry几何类常用方法简单整理
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6431245.html
Copyright © 2011-2022 走看看