算法描述:经典的求二分图最大匹配的算法是Edmond于1965年提出的匈牙利算法。算法的核心思想是由一个初始匹配不断找增广路,直到找不到增广路为止。这里的增广路和网络流中的增广路有些不同。这里的增广路是这样的一条路:设已有的匹配为M,它的第一条边不在M中,最后一条边也不在M中,中间为在M中的边与不在M中的边交错出现。显然,这条路起点在X中,终点在Y中,且不在M中的边比在M中的边多1。所以我们若对增广路中的边进行取反,即原来不是匹配边的边变为匹配边,原来是匹配边的边变为不是匹配边的边,则我们能获得一个更大的匹配。所以这么一直找下去,直到找不到增广路为止,我们最后得到的匹配M就是要求的最大匹配。
给定一个二分图G,M为G边集的一个子集,如果M满足当中的任意两条边都不依附于同一个顶点,则称M是一个匹配。应用匈牙利算法可以找图的最大匹配。
算法轮廓:
(1)置M为空
(2)找出一条增广路径P,通过取反操作获得更大的匹配M’代替M
(3)重复(2)操作直到找不出增广路
- /*pku1325
- Name: Machine Schedule
- Date: 24-07-08 21:48
- Description:一项工作可以由两机器在各自的模式下完成,模式的该变要
- 重启机器,在所给的任务中使用最少次数的重启,即模式切换次数最少 .
- 二分图的最大匹配即为最大匹配
- */
- #include<stdio.h>
- #include<algorithm>
- #define pr printf
- int min;
- int map[103][103];
- int nv[103],mv[103];
- bool visited[103];
- int n,m;
- int dfs(int n_v){
- int i;
- for(i=0;i<m;i++)
- {
- if(!visited[i] && map[n_v][i]==1){
- visited[i]=true;
- if(mv[i]==-1 || dfs(mv[i])==1){
- mv[i]=n_v;
- nv[n_v]=i;
- return 1;
- }
- }
- }
- return 0;
- }
- int main(){
- int k,i,a,b;
- while(scanf("%d",&n)){
- if(n==0)break;
- scanf("%d%d",&m,&k);
- memset(map,-1,sizeof(map));//-1表示不存在边 1存在
- for(i=k;i>=1;i--){
- scanf("%d%d%d",&k,&a,&b);
- if(a*b!=0){map[a][b]=map[a][b]=1;}
- // else k--;
- }
- int ans=0;
- memset(nv,-1,sizeof(nv));
- memset(mv,-1,sizeof(mv));
- for(i=0;i<n;i++){
- if(nv[i]==-1){//找到不在匹配中的x,作为起点
- memset(visited,0,sizeof(visited));
- if(dfs(i)==1)ans++;//每找到一次增广路径,匹配数+1
- }
- }
- pr("%d/n",ans);
- }
- }
本文介绍了一种解决二分图最大匹配问题的经典算法——匈牙利算法。通过不断寻找增广路径来逐步扩大匹配集合,直至无法再寻找到新的增广路径为止。文中还提供了一个具体的C语言实现案例。
8万+

被折叠的 条评论
为什么被折叠?



