hdu 2732 最大流

有一些蜥蜴在一个迷宫里面,求这些蜥蜴还有多少是无论如何都逃不出来的。蜥蜴最远能够跳跃距离D,若某一时刻蜥蜴能跳到迷宫外围,则算>蜥蜴逃出来了。每只蜥蜴有一个初始的位置,题目保证这些位置都有一些柱子,每次蜥蜴从一个位置跳到另外一个位置的时候,就会由于反作用力使得一根
柱子倒下。每根柱子都有最大jump数,若有超过jump个蜥蜴从该跟柱子跳过(也就是leap次),则柱子会倒塌。距离是算曼哈顿距离。




    建图:初始有蜥蜴的柱子和source连边,容量为1
          每个柱子拆成两个点,u -> u',容量为jump数
          能跳到外围的柱子和sink连边,容量infinite
          相距不超过D的柱子u,v,连边u' -> v 和 v' -> u,容量infinite



const  int  inf = 1000000000 ;
const  int  maxn = 20000 , maxm = 500000 ;
struct Edge{
       int v , f ,next ;
       Edge(){}
       Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}
};
int  sourse , meet ;
int  id ;
Edge e[maxm*2 + 10] ;
int  g[maxn + 10] ;

void  add(int u , int v , int f){
      e[++id] = Edge(v , f ,g[u]) ;
      g[u] = id ;
      e[++id] = Edge(u , 0 , g[v]) ;
      g[v] = id ;
}

queue <int> que ;
bool vis[maxn + 10] ;
int  dist[maxn + 10] ;

void bfs(){
     memset(dist , 0 , sizeof(dist)) ;
     while(! que.empty()) que.pop() ;
     que.push(sourse) ;
     vis[sourse] = 1 ;
     while(! que.empty()){
          int u = que.front() ;  que.pop() ;
          for(int i = g[u] ; i ; i = e[i].next){
               int v = e[i].v ;
               if(e[i].f && !vis[v]){
                     que.push(v) ;
                     dist[v] = dist[u] + 1 ;
                     vis[v] = 1 ;
               }
          }
     }
}

int  dfs(int u , int delta){
     if(u == meet) return delta ;
     int ans = 0 ;
     for(int i = g[u] ; i && delta ; i = e[i].next){
           int  v = e[i].v ;
           if(e[i].f && dist[v] == dist[u] + 1){
                int d = dfs(v , min(delta , e[i].f)) ;
                e[i].f -= d ;
                e[i^1].f += d ;
                delta -= d ;
                ans += d ;
           }
     }
     return ans ;
}

int  maxflow(){
     int ans = 0 ;
     while(1){
         memset(vis , 0 , sizeof(vis)) ;
         bfs() ;
         if(! vis[meet]) return ans  ;
         ans += dfs(sourse , inf) ;
     }
}

void init(){
     memset(g , 0 , sizeof(g)) ;
     id = 1 ;
}

char str[28][28] ;

int  main(){
     int n , m  , x , d , i , j , t  , T = 1 ;
     int u , v , w  , a , b  , sum ;
     cin>>t ;
     while(t--){
          cin>>n>>d ;
          init() ;
          for(i = 1 ; i <= n ; i++)
              scanf("%s" , str[i] + 1) ;
          m = strlen(str[1]+1) ;
          sourse = 0 , meet = n*m*2 + 1 ;
          for(i = 1 ; i <= n ; i++){
              for(j = 1 ; j <= m ; j++){
                   w = str[i][j] - '0' ;
                   u = (i-1)*m + j ;
                   add(u , u+n*m , w) ;
              }
          }
          for(i = 1 ; i <= n ; i++){
             for(j = 1 ; j <= m ; j++){
                 if(str[i][j] == '0') continue ;
                 for(a = 1 ; a <= n ; a++){
                     for(b = 1 ; b <= m ; b++){
                         if(str[a][b] == '0') continue ;
                         if(i == a && j == b) continue ;
                         if(abs(i - a) + abs(j - b) <= d){
                              u = (i-1)*m + j ;
                              v = (a-1)*m + b ;
                              add(u+n*m ,v , inf) ;
                              add(v+n*m , u , inf) ;
                         }
                     }
                 }
             }
          }
          for(i = 1 ; i <= n ; i++){
              for(j = 1 ; j <= m ; j++){
                   if(str[i][j] == '0') continue ;
                   if(i <= d || j <= d || i >= n-d+1 || j >= m-d+1){
                       u = (i-1)*m + j ;
                       add(u+n*m , meet , inf) ;
                   }
              }
          }
          sum = 0 ;
          for(i = 1 ; i <= n ; i++)  scanf("%s" , str[i]+1) ;
          for(i = 1 ; i <= n ; i++){
              for(j = 1 ; j <= m ; j++){
                  if(str[i][j] == 'L'){
                       sum++ ;
                       u = (i-1)*m + j ;
                       add(sourse , u , 1) ;
                  }
              }
          }
          sum -= maxflow() ;
          printf("Case #%d: " , T++) ;
          if(sum == 0) printf("no lizard was left behind.\n") ;
          else if(sum == 1) printf("1 lizard was left behind.\n") ;
          else printf("%d lizards were left behind.\n" , sum) ;
     }
     return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值