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
  • 相关阅读:
    2015531 网络攻防 Exp1 PC平台逆向破解(5)M
    2017-2018-1 20155331 嵌入式C语言
    20155330 《网络对抗》 Exp9 web安全基础实践
    20155330 《网络对抗》 Exp8 Web基础
    20155330 《网络对抗》 Exp7 网络欺诈防范
    20155330 《网络对抗》 Exp6 信息搜集与漏洞扫描
    20155330 《网络对抗》 Exp5 MSF基础应用
    20155330 《网络攻防》 Exp4 恶意代码分析
    20155330 《网络攻防》 Exp3 免杀原理与实践
    20155330 《网络对抗》 Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6431245.html
Copyright © 2011-2022 走看看