const int MAXN=550;// 最大点数
int bmap[MAXN][MAXN];//二分图
int cx[MAXN];//cx[i]表示左集合i顶点所匹配的右集合的顶点序号
int cy[MAXN]; //cy[i]表示右集合i顶点所匹配的左集合的顶点序号
int dis;
int n,m;
int dx[MAXN],dy[MAXN]; //dx表示到x的距离,dy表示到y的距离
int used[MAXN]; //在每次增广中是否使用i点
bool SearchPath() //bfs寻找增广路集
{
queue<int>Q;
dis = INF; //存每一次增广的距离
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=1;i<=n;i++)
{
if(cx[i]==-1) 将未遍历的节点入队,并初始化次节点距离为0
{
Q.push(i);
dx[i] = 0;
}
}
while(!Q.empty())
{
int u = Q.front();
Q.pop();
if(dx[u]>dis)
break;
//取右边的节点
for(int v=1;v<=m;v++)
{
if(bmap[u][v]&&dy[v]==-1)
{
dy[v] = dx[u] + 1; //v的距离为u的对应距离+1
if(cy[v]==-1) //如果该点未匹配,增广路形成
dis = dy[v];
else //如果该点已匹配,那么接着往下搜
{
dx[cy[v]] = dy[v] + 1;
Q.push(cy[v]);
}
}
}
}
return dis!=INF;
}
bool DFS(int u)
{
for(int v=1;v<=m;v++)
{
//如果该点没有被使用过,并且距离为上一节点+1
if(!used[v]&&bmap[u][v]&&dy[v]==dx[u]+1)
{
used[v] = 1; //标记使用过该点
//如果该点已经被匹配了并且为最后一个匹配点,那么这条路径不是增广路,即这条路的结点已经匹配
if(cy[v]!=-1&&dy[v]==dis)
continue;
if(cy[v]==-1||DFS(cy[v]))
{
cy[v]=u,cx[u]=v;
return true;
}
}
}
return false;
}
int MaxMatch()
{
int sum = 0;
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
while(SearchPath()) //当存在增广路,继续松弛
{
memset(used,0,sizeof(used)); //每一次的右边的点是否用过
for(int i=1;i<=n;i++)
{
if(cx[i]==-1&&DFS(i)) //如果当前这个点没连过,且能找到增宽路
sum++;
}
}
return sum;
}