Zoj--1654 (Hdu 5093) (二分图最大匹配,建图)

2014-11-04 13:48:34

思路:巧妙的建图,利用了“块”的思想,首先逐行扫,编号从1开始,依次给*编号。如果发现这一行中有#,那么让编号加一,再给后面的*编号。列的处理也是一样的。

  *ooo    1ooo      1ooo

  o### ->  o###(行编号) o###

  **#*    22#3       12#3

  ooo*         ooo4       ooo3

  最后的话就是那行和列编号进行匹配,为什么能这么做呢?

  分析:如果编号为2的行块 和 编号为5的列块相交于图中一个格子,那么如果在这个格子放船舰,那么行块2和列块5内都不能放置其他船舰了,也就是在行块2和列块5之间连上一条边,这样这两个点就不能再连边。于是整张图就有了最大匹配求最多船舰数这样的含义。

  1 /*************************************************************************
  2     > File Name: 5093.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Tue 04 Nov 2014 12:18:56 AM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 2510;
 27 
 28 int T;
 29 int n,m,cr,cc,row[55][55],col[55][55];
 30 char g[55][55];
 31 int first[maxn],next[maxn],ver[maxn],ecnt;
 32 int used[maxn],mat[maxn];
 33 
 34 void Init(){
 35     memset(row,0,sizeof(row));
 36     memset(col,0,sizeof(col));
 37     memset(first,-1,sizeof(first));
 38     ecnt = cr = cc = 0;
 39 }
 40 
 41 void Add_edge(int u,int v){
 42     next[++ecnt] = first[u];
 43     ver[ecnt] = v;
 44     first[u] = ecnt;
 45 }
 46 
 47 void Build_graph(){
 48     for(int i = 0; i < n; ++i){
 49         for(int j = 0; j < m; ++j){
 50             int u = row[i][j],v = col[i][j];
 51             if(u && v) Add_edge(u,v);
 52         }
 53     }
 54 }
 55 
 56 bool find(int p){
 57     for(int i = first[p]; i != -1; i = next[i]){
 58         int v = ver[i];
 59         if(used[v] == 0){
 60             used[v] = 1;
 61             if(mat[v] == 0 || find(mat[v])){
 62                 mat[v] = p;
 63                 return true;
 64             }
 65         }
 66     }
 67     return false;
 68 }
 69 
 70 int Hungary(){
 71     int ans = 0;
 72     memset(mat,0,sizeof(mat));
 73     for(int i = 1; i <= cr; ++i){
 74         memset(used,0,sizeof(used));
 75         if(find(i)) ++ans;
 76     }
 77     return ans;
 78 }
 79 
 80 int main(){
 81     scanf("%d",&T);
 82     int Case = 0;
 83     while(T--){
 84         Init();
 85         scanf("%d%d",&n,&m);
 86         for(int i = 0; i < n; ++i)
 87             scanf("%s",g[i]);
 88         for(int i = 0; i < n; ++i){
 89             int flag = 0;
 90             for(int j = 0; j < m; ++j){
 91                 if(g[i][j] == 'o'){
 92                     if(flag == 0) ++cr;
 93                     row[i][j] = cr;
 94                     flag = 1;
 95                 }
 96                 else if(g[i][j] == '#')
 97                     flag = 0;
 98             }
 99         }
100         for(int j = 0; j < m; ++j){
101             int flag = 0;
102             for(int i = 0; i < n; ++i){
103                 if(g[i][j] == 'o'){
104                     if(flag == 0) ++cc;
105                     col[i][j] = cc;
106                     flag = 1;
107                 }
108                 else if(g[i][j] == '#')
109                     flag = 0;
110             }
111         }
112         Build_graph();
113         printf("Case :%d\n",++Case);
114         printf("%d\n",Hungary());
115     }
116     return 0;
117 }

 

posted @ 2014-11-04 13:49  Naturain  阅读(141)  评论(0)    收藏  举报