两个集合
分别是按行和列凑成的点的集合
如图
1000
0000
2203
0004
1000
0000
1203
0003
两个集合构成的边,求该图的最大二分匹配
#include<bits/stdc++.h>
using namespace std;
bool edge[3000][3000];
char mapp[100][100];
int num1[100][100],num2[100][100],link[3000];
bool vis[3000];
int k1,k2,cnt;
bool dfs(int x)
{
for(int y=1;y<k2;y++)
if(edge[x][y]&&!vis[y])
{
vis[y]=1;
if(link[y]==0 || dfs(link[y]))
{
link[y]=x;
return true;
}
}
return false;
}
void search()
{
memset(link,0,sizeof(link));
for(int x=1;x<k1;x++)
{
memset(vis,0,sizeof(vis));
if(dfs(x)) cnt++;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
int N,M;
scanf("%d%d",&M,&N);
memset(edge,0,sizeof(edge));
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
memset(mapp,0,sizeof(mapp));
for(int i=1;i<=M;i++)
for(int j=1;j<=N;j++)
cin>>mapp[i][j];
k1=k2=1;
for(int i=1;i<=M;i++){
for(int j=1;j<=N;j++)
{
if(mapp[i][j]=='#') k1++;
if(mapp[i][j]=='*') num1[i][j]=k1;
}
k1++;
}
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++)
{
if(mapp[j][i]=='#') k2++;
if(mapp[j][i]=='*') num2[j][i]=k2;
}
k2++;
}
for(int i=1;i<=M;i++)
for(int j=1;j<=N;j++)
edge[ num1[i][j] ][ num2[i][j] ]=1;
cnt=0;
search();
printf("%d\n",cnt);
}
return 0;
}