一直想写点博客来记录一下自己的学习的点点滴滴,也是为了方便一下自己以后的查询。但是由于自己是在太拖沓了,迟迟没有行动起来,自己都对自己忍无可忍了。所以,下定决心要从今天开始把这件事情给坚持下来。希望自己能再其中不断的成长。
为了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; }
好吧,其实自己对该算法的理解还过于肤浅,今天只是做一下笔记,以免忘记。真正核心,自己理解的东西,还需要自己多刷两道题,过两天再补上。继续加油吧!!!