hdu1045 二分匹配
这题我是在总结过程中想找二分匹配做做的,如果是平时我估计就直接深搜了。。
二分匹配一开始没想出来如何建图,开始的思路有点阻塞,后来突然就明白了。
题意,给一个n*n的棋盘 图中有X和。其中X代表墙,问棋盘中最多能放多少个‘车’使每个车都安全。
先对行搜索,一行中若隔一个X则相当于有2行,找出所有的行并标上序号,然后对列同样进行操作。这样二分图的两边的点就全找出来了。
然后对于图中每一个‘。’号进行连边将L【i】【j】与R【i】【j】相连,求最大匹配即是答案。
代码:
#include<iostream> #include<cstring> const int MAXN = 100; using namespace std; struct g{ int num; int boy[MAXN]; }gr[MAXN]; bool flag[MAXN]; int pre[MAXN]; int n,m; int DFS(int x) { for(int i=0;i<gr[x].num;i++) //男生 { if(!flag[gr[x].boy[i]]) //未被匹配 { flag[gr[x].boy[i]]=true; if(pre[gr[x].boy[i]]==-1||DFS(pre[gr[x].boy[i]])) { pre[gr[x].boy[i]]=x; //第几个女生 return 1; } } } return 0; } char c[5][5]; int r[5][5]; int l[5][5]; int main() { int sum,k,a,b; while(cin>>n&&n!=0) { for(int i=0;i<n;i++) { cin>>c[i]; } //找行 标号 int temp=1; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(c[i][j]=='X') {temp++;r[i][j]=-1;} else r[i][j]=temp; if(j==n-1)temp++; } } int rn=temp-1; //找列 temp=1; for(int j=0;j<n;j++) { for(int i=0;i<n;i++) { if(c[i][j]=='X') { temp++;l[i][j]=-1; } else l[i][j]=temp; if(i==n-1)temp++; } } int ln=temp-1; for(int i=0;i<=10;i++) gr[i].num=0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(l[i][j]!=-1) { gr[r[i][j]].boy[gr[r[i][j]].num++]=l[i][j]; } } sum=0; memset(pre,-1,sizeof(pre)); for(int i=1;i<=rn;i++) //行 { memset(flag,0,sizeof(flag)); sum+=DFS(i); } cout<<sum<<endl; } return 0; }