hdu-1054(二分图最大匹配)
题意:给你一个图,图里有墙壁和空地,空地可以放置一台机关枪,机关枪可以朝着四个方向发射,子弹不能穿透墙壁,但是射程无限,机关枪会被损坏如果被另一台机关枪的子弹打到,问你最多能放置多少台机关枪;
解题思路:考虑每台机关枪实际能够朝行和列两个方向开火,根据贪心的想法,尽可能不在某行和某列的交点放置,那么如果我们把行和列分成x,y两部分,每行中能够连接的空地当作x的一个顶点,每列中能够连接的空地当作y的一个顶点,问题转换为在二分图中找没有公共顶点的最大边集,也就是二分图最大匹配
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; int n; char s[10][10]; int match[50]; int visit[50]; int gra[50][50]; int row[50][50],col[50][50]; int c,r; int dfs(int u) { for(int i=1;i<c;i++) { if(gra[u][i]&&visit[i]==0) { visit[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=u; return 1; } } } return 0; } int main() { while(cin>>n&&n) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>s[i][j]; c=r=1; memset(row,-1,sizeof(row)); memset(col,-1,sizeof(col)); memset(match,-1,sizeof(match)); memset(visit,0,sizeof(visit)); memset(gra,0,sizeof(gra)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(s[i][j]=='.'&&row[i][j]==-1)//找每行的顶点 { for(int k=j;k<=n;k++) if(s[i][k]=='.') row[i][k]=r; else//遇到墙壁结束 break; r++;//顶点+1 } } for(int j=1;j<=n;j++) { if(s[j][i]=='.'&&col[j][i]==-1) { for(int k=j;k<=n;k++) if(s[k][i]=='.') col[k][i]=c; else break; c++; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { gra[row[i][j]][col[i][j]]=1; } } int ans=0; for(int i=1;i<r;i++) { memset(visit,0,sizeof(visit)); if(dfs(i)) { ans++; } } cout<<ans<<endl; } }