UVA 10888 km 题库61页

来源:互联网 发布:欧文生涯数据统计 编辑:程序博客网 时间:2024/05/23 01:17

 注意求最小值的方法。

const  int  maxn = 108 ;int    lx[maxn] , ly[maxn] ;int    Left[maxn] ;int    w[maxn][maxn] ;bool   S[maxn] , T[maxn] ;int    n  ;bool   match(int i){       S[i] = 1 ;       for(int j = 1 ; j <= n ; j++){            if(!T[j] && lx[i] + ly[j] == w[i][j]){                  T[j] = 1 ;                  if(!Left[j] || match(Left[j])){                       Left[j] = i ;                       return 1 ;                  }            }       }       return 0 ;}void   update(){       int a = 1<<30 ;       for(int i = 1 ; i <= n ; i++){            if(S[i]){                for(int j = 1 ; j <= n ; j++){                    if(! T[j]) a = min(a , lx[i]+ly[j]-w[i][j]) ;                }            }       }       for(int i = 1 ; i <= n ; i++){            if(S[i])  lx[i] -= a ;            if(T[i]) ly[i] += a ;       }}int    km(){       for(int i = 1 ; i <= n ; i++){            Left[i] = lx[i] = ly[i] = 0 ;            for(int j = 1 ; j <= n ; j++)                lx[i] = max(lx[i] , w[i][j]) ;       }       for(int i = 1 ; i <= n ; i++){            while(1){                for(int j = 1 ; j <= n ; j++)                    S[j] = T[j] = 0 ;                if(match(i)) break  ;                else   update() ;            }       }       int  s = 0 ;       for(int i = 1 ; i <= n ; i++) s += w[Left[i]][i] ;       return s  ;}char  g[48][48]  ;int   N , M  ;int   can(int x , int y){      return 1 <= x && x <= N && 1 <= y && y <= M ;}int   d[4][2] = {{-1,0},{0,-1},{1,0},{0,1}} ;int   dist[48][48] ;bool  in[48][48]  ;vector<pair<int , int> > lisx , lisb ;void  bfs(int sx , int sy , int id){      queue< pair<int ,int> > q ;      q.push(make_pair(sx,sy)) ;      memset(dist , 63 , sizeof(dist)) ;      dist[sx][sy] = 0  ;      in[sx][sy] = 1 ;      while(! q.empty()){            pair<int , int> now = q.front() ;            q.pop() ;            in[now.first][now.second] = 0 ;            for(int i = 0 ; i < 4 ; i++){                 int x = now.first + d[i][0]  ;                 int y = now.second + d[i][1] ;                 if(! can(x , y) || g[x][y] == '#') continue ;                 if(dist[x][y] > dist[now.first][now.second] + 1){                       dist[x][y] = dist[now.first][now.second] + 1 ;                       if(!in[x][y]){                            in[x][y] = 1 ;                            q.push(make_pair(x , y)) ;                        }                 }            }      }      for(int i = 0 ; i < lisb.size() ; i++){           w[id][i+1] = min(w[id][i+1] , dist[lisb[i].first][lisb[i].second]) ;      }}int  main(){     int t , i , j , b , x ;     cin>>t ;     while(t--){          cin>>N>>M ;          for(i = 1 ; i <= N ; i++) scanf("%s" , g[i]+1) ;          lisx.clear() ;          lisb.clear() ;          for(i = 1 ; i <= N ; i++){              for(j = 1 ; j <= M ; j++){                  if(g[i][j] == 'B')                        lisb.push_back(make_pair(i , j)) ;                  else if(g[i][j] == 'X')                        lisx.push_back(make_pair(i , j)) ;              }          }          n = lisb.size() ;          memset(w , 63 , sizeof(w)) ;          for(i = 0 ; i < lisx.size() ; i++){               bfs(lisx[i].first , lisx[i].second , i+1) ;          }          for(i = 1 ; i <= n ; i++)             for(j = 1 ; j <= n ; j++){                    w[i][j] = -w[i][j] ;             }          cout<< -km() << endl  ;     }     return  0 ;}


0 0