二分图最大匹配之匈牙利算法模板

匈牙利算法的原理为:从当前匹配M(如果没有匹配,则取初始匹配为M=Ø)出发,检查每一个未盖点,然后从它出发寻找可增广路,找到可增广路,则沿着这条可增广路进行扩充,直到不存在可增广路为止。

根据从未盖点出发寻找可增广路搜索的方法,可以分为:
1) DFS增广;
2) BFS增广;
3)  多增广路(Hopcroft-Karp算法)

 

本文只实现1),2)两种方法

 

const int MAXN = 11;
int nx, ny;//集合X和Y中的顶点最大数
int g[MAXN][MAXN];//g[i][j]表示xi与yj有边相连
int cx[MAXN], cy[MAXN];//cx[i]表示最终求得的最大匹配中与Xi匹配的顶点y,cy[j]同


BFS搜索

int MaxMatch()
{
     int i, j, y;
     int cur, tail;
     int res = 0;//所求得的最大的匹配数
     memset(cx, 0xff, sizeof(cx));//初始化所有点都是未匹配点
     memset(cy, 0xff, sizeof(cy));
     for(i = 0; i < nx; ++i)
     {
          if(cx[i] != -1)
               continue;
          //对X集合中的每个未盖点i进行一次BFS搜索,找交错轨
          for(j = 0; j < ny; ++j)
               pred[j] = -2;
          cur = tail = 0;
          for(j = 0; j < ny; ++j)//把顶点i的邻接顶点都入队列
          {
               if(g[i][j])
               {
                    pred[j] = -1;//表示i点已经访问过了。
                    queue[tail++] = j;
               }
          }

          while(cur < tail)
          {
               y = queue[cur];
               if(cy[y] == -1)//找到一个未盖点,也即是找到一条交错轨
                    break;
               cur++;
               //能走到这一步,说明:y已经匹配给cy[y]了,然后再从cy[y]开始出发,将它的邻接顶点入队列
               for(j = 0; j < ny; ++j)
               {
                    if(pred[j] == -2 && g[ cy[y] ][j])
                    {
                         pred[j] = y;
                         queue[tail++] = j;
                    }
               }
          }
          if(cur == tail)//你没有找到交错轨
               continue;
          while( pred[y] > -1)//更改交错轨上的匹配状态
          {
               cx[ cy[ pred[y] ] ] = y;
               cy[y] = cy[ pred[y] ];
               y = pred[y];
          }
          cy[y] = i;
          cx[i] = y;
          res++;//匹配数加1
     }
     return res;
}


 

 

 

DFS搜索

 

//DFS增广

int visited[MAXN];
//从X集合中的顶点u出发,用深度优先搜索的策略寻找增广路
//这种增广路只能使当前的匹配数加1

int Path( int u )
{
     for(int j = 0; j < ny; ++j)
     {
          if(!visited[j] && g[u][j])
          {
               visited[j] = 1;
               //如果j没有匹配或者已经匹配了,但是从cy[j]可以找到一条增广轨
               //如果前一个条件成立就不会产生递归调用
               if(cy[j] == -1 || Path( j ))
               {
                    cx[u] = j;//把j匹配给u
                    cy[j] = u;//把u匹配给j
                    return 1;//找到了增广路
               }
          }
     }
     return 0;
}

int MaxMatch()
{
     int res = 0;
     memset(cx, 0xff, sizeof(cx));
     memset(cy, 0xff, sizeof(cy));
     for(int i = 0; i < nx; ++i)
     {
          if(cx[i] == -1)
          {
               memset(visited, 0, sizeof(visited));
               res += Path( i );
          }
     }
     return res;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值