二分图最大匹配(匈牙利算法)

算法轮廓:
(1)置M为空
(2)找出一条增广路径P,通过取反操作获得更大的匹配M’代替M
(3)重复(2)操作直到找不出增广路径为止


下面是匈牙利算法的c语言模板:

#include  < stdio.h >
#include 
< cstring >

// 匈牙利算法
int   xv = 5 ,yv = 5 ,n = 5 ;      //  顶点数(数字5认你定) 
int   g[ 5 ][ 5 ];      //  g[i][j]=1 表示 xi与yj相邻 
int   sy[ 5 ];      //  辅助:当轮被搜过的y点都是1  
int   cnt,xm[ 5 ],ym[ 5 ];   //  输出  
void   init()
{
    cnt
= 0  ;
    memset(g, 
0  , sizeof (g));
    memset(xm,
- 1 , sizeof (xm));
    memset(ym,
- 1 , sizeof (ym));

int  path( int  u)  //  返回是否找到增广路(递归,时间复杂度O(n*n)) 
{
    
int  v;
    
for (v = 0 ;v < yv;v ++ )
    {
        
if ((g[u][v] == 1 ) && (sy[v] == 0 ))  
        { 
            sy[v]
= 1 ;
            
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
            {
                xm[u]
= v;ym[v] = u;
                
return   1 ;
            } 
        }
    }
    
return   0 ;   

void  main()
{
    
int   i,j;
    
// 初始化
    init();
    
for (i = 0 ;i < n;i ++ )
    {
        
for (j = 0 ;j < n;j ++ )
        {
            scanf(
" %d " , & g[i][j]);
        }
    }
    
// 核心
     for (i = 0 ;i < xv;i ++ )
    {
        
if (xm[i] ==- 1 )
        {
            memset(sy,
0 , sizeof (sy));
            cnt
+= path(i);
        }
    }
    
// 打印
    printf( " sum=%d " ,cnt);
}
PKU-1469(一道经典简单的最大匹配题)我们只要把上面的模板修改一下就能解出这题:
下面是AC-Code:
 
   
#include  < stdio.h >
#include 
< string .h >

const   int  MAXN  =   500 ;
int   xv,yv,n;      //  顶点数(数字5认你定) 
int   g[MAXN][MAXN];      //  g[i][j]=1 表示 xi与yj相邻 
int   sy[MAXN];      //  辅助:当轮被搜过的y点都是1  
int   cnt,xm[MAXN],ym[MAXN];   //  输出  

void   init()
{
    cnt
= 0  ;
    memset(g, 
0  , sizeof (g));
    memset(xm,
- 1 , sizeof (xm));
    memset(ym,
- 1 , sizeof (ym));


int  path( int  u)  //  返回是否找到增广路(递归,时间复杂度O(n*n)) 
{
    
int  v;
    
for (v = 0 ;v < yv;v ++ )
    {
        
if ((g[u][v] == 1 ) && (sy[v] == 0 ))  
        { 
            sy[v]
= 1 ;
            
if ((ym[v] ==- 1 ) || (path(ym[v]) == 1 ))
            {
                xm[u]
= v;ym[v] = u;
                
return   1 ;
            } 
        }
    }
    
return   0 ;   


// 按模板作出修改
int  main()
{
    
int   i,j,s,t,da;
    
    scanf(
" %d " , & n);
    
for (s = 0 ;s < n;s ++ )
    {
       
// 初始化
       init();
       scanf(
" %d%d " , & xv, & yv);
      
for (i = 0 ;i < xv;i ++ )
      {
          scanf(
" %d " , & t);
        
for (j = 0 ;j < t;j ++ )
        {
            scanf(
" %d " , & da);
            g[i][da
- 1 =   1 ;
        }
      }
       
// 核心
       for (i = 0 ;i < xv;i ++ )
      {
        
if (xm[i] ==- 1 )
        {
            memset(sy,
0 , sizeof (sy));
            cnt
+= path(i);
        }
      }
      
      
if (cnt == xv) printf( " YES " );
      
else  printf( " NO " );

    }
    
return   0 ;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值