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 }

浙公网安备 33010602011771号