zoukankan      html  css  js  c++  java
  • HDU 2732 Leapin' Lizards(最大流)

    http://acm.hdu.edu.cn/showproblem.php?pid=2732

    题意:

    给出n行的网格,还有若干只蜥蜴,每只蜥蜴一开始就在一个格子之中,并且给出蜥蜴每次的最大跳跃长度d。每个格子中有一个数字,代表从这个格子中最多能跳出几只蜥蜴,之后就不能有蜥蜴再跳入这个格子之中了。求出最后最少有几只蜥蜴不能跳出网格。

    思路:

    关键是建图。

    设汇点就是跳出网格。

    每个格子跳出的蜥蜴数是有限制的,那么这就很明显的是要拆点,容量为允许跳出的蜥蜴数。如果在这个格子上能跳出网格,那就将这个格子与汇点连接起来,容量为INF。如果不能的话,它可以跳到别的格子中去,所以与它距离小于等于d的格子要与之相连,容量为INF。

    蜥蜴所在的格子就与源点相连,最后求得的最大流就是能跳出网格的蜥蜴的最大值。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<queue>
      6 using namespace std;
      7 
      8 const int maxn=1000+5;
      9 const int INF=0x3f3f3f3f;
     10 
     11 
     12 struct Edge
     13 {
     14     int from,to,cap,flow;
     15     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     16 };
     17 
     18 struct Dinic
     19 {
     20     int n,m,s,t;
     21     vector<Edge> edges;
     22     vector<int> G[maxn];
     23     bool vis[maxn];
     24     int cur[maxn];
     25     int d[maxn];
     26 
     27     void init(int n)
     28     {
     29         this->n=n;
     30         for(int i=0;i<n;++i) G[i].clear();
     31         edges.clear();
     32     }
     33 
     34     void AddEdge(int from,int to,int cap)
     35     {
     36         edges.push_back( Edge(from,to,cap,0) );
     37         edges.push_back( Edge(to,from,0,0) );
     38         m=edges.size();
     39         G[from].push_back(m-2);
     40         G[to].push_back(m-1);
     41     }
     42 
     43     bool BFS()
     44     {
     45         queue<int> Q;
     46         memset(vis,0,sizeof(vis));
     47         vis[s]=true;
     48         d[s]=0;
     49         Q.push(s);
     50         while(!Q.empty())
     51         {
     52             int x=Q.front(); Q.pop();
     53             for(int i=0;i<G[x].size();++i)
     54             {
     55                 Edge& e=edges[G[x][i]];
     56                 if(!vis[e.to] && e.cap>e.flow)
     57                 {
     58                     vis[e.to]=true;
     59                     d[e.to]=d[x]+1;
     60                     Q.push(e.to);
     61                 }
     62             }
     63         }
     64         return vis[t];
     65     }
     66 
     67     int DFS(int x,int a)
     68     {
     69         if(x==t || a==0) return a;
     70         int flow=0, f;
     71         for(int &i=cur[x];i<G[x].size();++i)
     72         {
     73             Edge &e=edges[G[x][i]];
     74             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     75             {
     76                 e.flow +=f;
     77                 edges[G[x][i]^1].flow -=f;
     78                 flow +=f;
     79                 a -=f;
     80                 if(a==0) break;
     81             }
     82         }
     83         return flow;
     84     }
     85 
     86     int Maxflow(int s,int t)
     87     {
     88         this->s=s; this->t=t;
     89         int flow=0;
     90         while(BFS())
     91         {
     92             memset(cur,0,sizeof(cur));
     93             flow +=DFS(s,INF);
     94         }
     95         return flow;
     96     }
     97 }DC;
     98 
     99 int n,d,m;
    100 int src,dst;
    101 
    102 int main()
    103 {
    104     //freopen("D:\input.txt","r",stdin);
    105     int T;
    106     string s;
    107     scanf("%d",&T);
    108     for(int kase=1;kase<=T;kase++)
    109     {
    110         scanf("%d%d",&n,&d);
    111         for(int i=1;i<=n;i++)
    112         {
    113             cin>>s;
    114             if(i==1)
    115             {
    116                 m=s.size();
    117                 src=0;
    118                 dst=2*n*m+1;
    119                 DC.init(2*n*m+2);
    120             }
    121             for(int j=0;j<m;j++)
    122             if(s[j]-'0'>0)
    123             {
    124                 int id=(i-1)*m+j+1;
    125                 DC.AddEdge(id,id+n*m,s[j]-'0');    //拆点,容量为最多能跳出的蜥蜴数
    126                 if(i<=d ||(i+d)>n ||(j+1)<=d || (j+1+d)>m)  DC.AddEdge(id+n*m,dst,INF);   //能跳出网格
    127                 else
    128                 {
    129                     for(int x=1;x<=n;x++)
    130                     for(int y=1;y<=m;y++)
    131                     {
    132                         if(x==i && y==j+1)  continue;
    133                         if(abs(x-i)+abs(y-j-1)<=d)  DC.AddEdge(id+n*m,(x-1)*m+y,INF);
    134                     }
    135                 }
    136             }
    137         }
    138         int sum=0;
    139         for(int i=1;i<=n;i++)
    140         {
    141             cin>>s;
    142             for(int j=0;j<m;j++)
    143             {
    144                 if(s[j]=='L')
    145                 {
    146                     sum++;
    147                     int id=(i-1)*m+j+1;
    148                     DC.AddEdge(src,id,1);
    149                 }
    150             }
    151         }
    152         int ans=sum-DC.Maxflow(src,dst);
    153         if(ans==0) printf("Case #%d: no lizard was left behind.
    ",kase);
    154         else if(ans==1) printf("Case #%d: 1 lizard was left behind.
    ",kase);
    155         else printf("Case #%d: %d lizards were left behind.
    ",kase,ans);
    156     }
    157     return 0;
    158 }
  • 相关阅读:
    [SCOI2016] 幸运数字
    [CF438E] 小朋友和二叉树
    【题解】[AHOI2013]作业
    【题解】CF940F Machine Learning
    【题解】CF1207E XOR Guessing
    【题解】CF1228D Complete Tripartite
    【题解】CF1290B Irreducible Anagrams
    【题解】[JSOI2007]字符加密
    【题解】[SDOI2016]征途
    【题解】多边形染色
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6686618.html
Copyright © 2011-2022 走看看