思路
匈牙利算法就是求最大匹配的算法。
首先,我们来几个前置知识。
- 增广路指的是匹配过和没匹配过的边交替出现的路径,第一个边是没匹配过的边,最后一个边也是没匹配过的边
因为增广路径中的没匹配边比匹配边多,所以我们将这中间的匹配边变成没匹配边,没匹配边变成匹配边,这样子我们的答案就能加一
我们要知道,找增广路的时候,出发点和结束点都是没匹配过的点,出发点在x部,结束点在y部
所以我们的问题就变成了找增广路径,因为如果没有增广路径了,就说明你的答案无法在增加了。
代码(有注释)
/*
dx[i] x部中第i个点和谁匹配
dy[i] y部中第i个点和谁匹配
bz[i] y部中第i个点有没有被找过
a[i][j] 邻接表存路径
*/
bool dfs(int x)
{
if(x==-1) return true;//如果上一个点没有匹配过的边,就说明上一个点是结束点
int to;
for(int i=1;i<=s[x];i++)
{
to=a[x][i];
if(!bz[to])//如果没被找过
{
bz[to]=1;
if(dfs(dy[to]))//如果从y部所匹配的点出发,能否找到一条增广路径,这里把找大增广路径变成了找小增广路径
{
dy[to]=x,dx[x]=to;//改变他们的匹配点
return true;
}
}
}
return false;
}
int hungry()
{
int ans=0;
memset(dx,-1,sizeof(dx)),memset(dy,-1,sizeof(dy));//刚开始x部和y部没有匹配边
for(int i=1;i<=n;i++)
{
if(dx[i]==-1)//如果这个点没匹配过
{
memset(bz,0,sizeof(bz));
ans+=dfs(i);//找到一条增广路径答案就可以加一
}
}
return ans;
}