poj 2226 二分图最大匹配
题意:在NxN的网格上,有一些格点是草地,有一些格点是泥地,给你一些宽度为1的长度不限的木板,将泥地全部覆盖,木板可以互相重叠但不能覆盖草地(这一点不同于poj3041)
思路:建图比较难想,将每一行上连续的泥地和每一列上连续的泥地计为二分图中的点,每一块泥地对应二分图中的边,就能将问题转化为最小点覆盖,求二分图最大匹配即可
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 6 const int maxn = 555; 7 bool ma[maxn][maxn]; 8 char g[maxn][maxn]; 9 int sign[maxn][maxn]; 10 int link[maxn]; 11 bool check[maxn]; 12 int nx,ny; 13 14 bool dfs(int u){ 15 for(int i = 1; i <= ny; ++i){ 16 if(!check[i] && ma[u][i]){ 17 check[i] = true; 18 if(link[i] == -1 || dfs(link[i])){ 19 link[i] = u; 20 return true; 21 } 22 } 23 } 24 return false; 25 } 26 27 int hungarian(){ 28 int ans = 0; 29 memset(link,-1,sizeof(link)); 30 for(int i = 1; i <= nx; ++i){ 31 memset(check,0,sizeof(check)); 32 if(dfs(i)) ++ans; 33 } 34 return ans; 35 } 36 37 int main(){ 38 int r,c; 39 scanf("%d%d",&r,&c); 40 char str[55]; 41 for(int i = 0; i < r; ++i){ 42 scanf("%s",g[i]); 43 } 44 nx = 0, ny = 0; 45 for(int i = 0; i < r; ++i){ 46 for(int j = 0; j < c; ++j){ 47 if(g[i][j] == '*'){ 48 nx++; 49 while(j < c && g[i][j] == '*'){ 50 sign[i][j++] = nx; 51 } 52 } 53 } 54 } 55 for(int j = 0; j < c; ++j){ 56 for(int i = 0; i < r; ++i){ 57 if(g[i][j] == '*'){ 58 ny++; 59 while(i < r && g[i][j] == '*'){ 60 ma[sign[i][j]][ny] = true; 61 i++; 62 } 63 } 64 } 65 } 66 printf("%d\n",hungarian()); 67 return 0; 68 }