pku 1325 Machine Schedule(匈牙利算法)

本文介绍了一种解决二分图最大匹配问题的经典算法——匈牙利算法。通过不断寻找增广路径来逐步扩大匹配集合,直至无法再寻找到新的增广路径为止。文中还提供了一个具体的C语言实现案例。
       这是道很简单的二分图匹配问题,第一次遇到这类题在网上找了一些资料。

        算法描述:经典的求二分图最大匹配的算法是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)操作直到找不出增广路

  1. /*pku1325
  2.   Name: Machine Schedule
  3.   Date: 24-07-08 21:48
  4.   Description:一项工作可以由两机器在各自的模式下完成,模式的该变要
  5.   重启机器,在所给的任务中使用最少次数的重启,即模式切换次数最少 .
  6.   二分图的最大匹配即为最大匹配       
  7. */
  8. #include<stdio.h>
  9. #include<algorithm>
  10. #define pr printf
  11. int min;
  12. int map[103][103];
  13. int nv[103],mv[103];
  14. bool visited[103];
  15. int n,m;
  16. int dfs(int n_v){
  17.     int i;
  18.     for(i=0;i<m;i++)
  19.     {
  20.         if(!visited[i] && map[n_v][i]==1){
  21.             visited[i]=true;
  22.             if(mv[i]==-1 || dfs(mv[i])==1){
  23.                 mv[i]=n_v;
  24.                 nv[n_v]=i;
  25.                 return 1;
  26.             }
  27.         }   
  28.     }   
  29.     return 0;
  30. }
  31. int main(){
  32.     int k,i,a,b;
  33.     while(scanf("%d",&n)){
  34.         if(n==0)break;
  35.         scanf("%d%d",&m,&k);
  36.         memset(map,-1,sizeof(map));//-1表示不存在边 1存在
  37.         for(i=k;i>=1;i--){
  38.             scanf("%d%d%d",&k,&a,&b);
  39.             if(a*b!=0){map[a][b]=map[a][b]=1;}
  40.                     //    else k--;
  41.             }
  42.             int ans=0;
  43.             memset(nv,-1,sizeof(nv));
  44.             memset(mv,-1,sizeof(mv));
  45.             for(i=0;i<n;i++){
  46.                 if(nv[i]==-1){//找到不在匹配中的x,作为起点
  47.                     memset(visited,0,sizeof(visited));
  48.                     if(dfs(i)==1)ans++;//每找到一次增广路径,匹配数+1
  49.                     }
  50.                 }
  51.             pr("%d/n",ans);
  52.         }
  53.     } 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值