考查:二分图最大匹配 最小顶点覆盖
提交情况:1次WA 一次AC
二分图最大匹配的问题一般用匈牙利算法解决,自己对匈牙利算法的理解就是在图中的每个点进行深度优先遍历,找到一条增广路径,然后对增光路径进行取反,直到找不到增广路径为止。因为增广路径是由不在匹配中的边和在匹配中的边交叉组成的,所以每反转一次匹配数就会增加1.具体的内容可以看下面的文章,说得非常好。
http://www.byvoid.com/blog/hungary/
http://imlazy.ycool.com/post.1603708.html
AC_CODE:
#include <stdio.h>
#include <string.h>
int graph[502][502];
int visit[502];
int match[502];
int N,K;
int dfs(int v)
{
int i;
for(i=1;i<=N;i++)
{
if(graph[v][i]&&!visit[i])
{
visit[i]=1;
if(match[i]==0||dfs(match[i]))
{
match[i]=v;
return 1;
}
}
}
return 0;
}
void hungary()
{
int i,cnt;
cnt=0;
for(i=1;i<=N;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i)) cnt++;
}
printf("%d\n",cnt);
}
int main()
{
int a,b;
memset(graph,0,sizeof(graph));
memset(match,0,sizeof(match));
scanf("%d %d",&N,&K);
while(K--)
{
scanf("%d %d",&a,&b);
graph[a][b]=1;
}
hungary();
return 0;
}
再说下代码和算法的具体关系。dfs函数的作用是从某个顶点v开始找一条增广路径,同时进行反转。过程是如果从v到另一个顶点v0有边而且另外一条边还没有被匹配,则就把v设为v0的匹配,或者如果v0已经被匹配了而且从v0开始可以找得到另外一条增广路径,则修改v0的匹配为v,这样就完成了反转。一般找不到增广路径时的情况为深度优先遍历到的最后一个点已经被匹配了,因为增广路径的起始点和结束点必须都为未匹配。
另外,二分图匹配还可以由HopCroft-Karp算法来做,它的复杂度为O(|E||V|^0.5),匈牙利算法的复杂度为O(|V||E|)。