匈牙利算法小心得

     一直想写点博客来记录一下自己的学习的点点滴滴,也是为了方便一下自己以后的查询。但是由于自己是在太拖沓了,迟迟没有行动起来,自己都对自己忍无可忍了。所以,下定决心要从今天开始把这件事情给坚持下来。希望自己能再其中不断的成长。

      为了12月15号的一个比赛,今天不迫不得已,又开始复习算法了。以前就看过匈牙利算法,当时也是搞得一知半解的,今天又遇到了,由于时间太久,完全忘记了他是什么东西,又重新学习了一遍。网上的博客资料什么的,好多都是讲得十分粗糙,让我越发的迷惑,好在山重水复疑无路,柳暗花明又一村,终于找到了一篇比较好的博文,让自己开了窍。

    先把博客地址贴出来吧,真是太感谢那位博主了。http://kukumayas.iteye.com/blog/1075610

    博主关于算法的过程和预备知识,那位博主已经讲得非常的清晰和详尽。我也不用再赘述了。知识在此总结一下,自己觉得需要注意的几个点。

 1.匈牙利算法有基于bfs和dfs的,博主的图片是给的基于dfs的。

 2. 算法的核心步骤就是:

   (1)把二分图分成两个集合A,B。并在进行最大匹配之前,做一些初始化的工作。

    (2)对于A中每一个节点要做的操作就是:从该节点顺序去找B中与之连通的节点g,g节点已经包含在M之中,则试图再从g出发去找到一条交错路径/增广路径。如果找到了则更新M。否则则继续查找下一个节点。

3.代码,这是百度文库里面的代码,写得非常的清晰和详尽。

#include <stdio.h>
#include <string.h>
int n1,n2,m,ans;
int result[101]; //记录V2中的点匹配的点的编号
bool state [101]; //记录V2中的每个点是否被搜索过
bool data[101][101];//邻接矩阵 true代表有边相连
void init() {
    int t1,t2;
    memset(data,0,sizeof(data));
    memset(result,0,sizeof(result));
    ans = 0;
    scanf("%d%d%d",&n1,&n2,&m);
    for (int i = 1; i <= m; i++) {
        scanf("%d%d",&t1,&t2);
        data[t1][t2] = true;
    }
    return;
}
bool find(int a) {
    for (int i = 1; i <= n2; i++) {
        if (data[a][i] == 1 && !state[i]) { //如果节点i与a相邻并且未被查找过,对于每一个节点使之往后查找新的匹配节点
            state[i] = true; //标记i为已查找过
            if (result[i] == 0 //如果i未在前一个匹配M中
            || find(result[i])) { //i在匹配M中,但是从与i相邻的节点出发可以有增广路,在进行这个递归查询的时候,其实就已经就实现了,断开增广路径,增加一条匹配记录的效果
                result[i] = a; //记录查找成功记录
                return true; //返回查找成功
            }
        }
    }
    return false;
}
int main() {
    init();
    for (int i = 1; i <= n1; i++) {//对每一个节点进行同样的操作
        memset(state,0,sizeof(state)); //清空上次搜索时的标记
        if (find(i)) ans++; //从节点i尝试扩展
    }
    printf("%d\n",ans);
    return 0;
}

好吧,其实自己对该算法的理解还过于肤浅,今天只是做一下笔记,以免忘记。真正核心,自己理解的东西,还需要自己多刷两道题,过两天再补上。继续加油吧!!!

点赞