HDU 1045
二分图匹配
题意:给你一个矩阵,X所在的地方是墙,往上面放碉堡,碉堡所在的行和列上的所有的点消灭掉。
与最简单的二分图不同的是,有墙。
做二分图的题,第一步要建图,在这里,二分图是一条边的两端分处于不同的点集、所以每找到一个点就把和他同一行、同一列的点都做同样的标记。遇到墙就停下
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define N 8 int cnt_row, cnt_col; int row[N][N], col[N][N], r[N], c[N]; char map[N][N]; bool path[N][N], vis[N]; int dfs(int rr) { for(int i=0;i<cnt_col;++i) { if(path[rr][i]&&vis[i]==false) { vis[i]=true; if(c[i]==-1||dfs(c[i])) { c[i]=rr; r[rr]=i; return 1; } } } return 0; } int maxmatch() { int ans=0; memset(r,-1,sizeof(r)); memset(c,-1,sizeof(c)); for(int i=0;i<cnt_row;i++) { if(r[i]==-1) { memset(vis,false,sizeof(vis)); ans+=dfs(i); } } return ans; } int main() { int n; while(~scanf("%d",&n)&&n) { for(int i = 0; i < n; ++i) { scanf("%s",map[i]); } memset(row,-1,sizeof(row)); memset(col,-1,sizeof(col)); cnt_row=cnt_col=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(map[i][j]=='.'&&row[i][j]==-1) { for(int k=j;map[i][k]=='.'&&k<n;++k) { row[i][k]=cnt_row; } cnt_row++; } if(map[j][i]=='.'&&col[j][i]==-1) { for(int k=j;map[k][i]=='.'&&k<n;++k) { col[k][i]=cnt_col; } cnt_col++; } } } memset(path,false,sizeof(path)); for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { if(map[i][j]=='.') { path[row[i][j]][col[i][j]]=true; } } } printf("%d\n",maxmatch()); } return 0; }