二分图匹配学习笔记

匈牙利算法是利用增广路来求最大匹配的,关于增广路有如下性质:
(1)有奇数条边。
(2)起点在二分图的左半边,终点在右半边。
(3)路径上的点一定是一个在左半边,一个在右半边,交替出现。
(4)整条路径上没有重复的点。
(5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。
(6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。
(7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原
匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。

同时从网上了解到有部分题目可以转换求最大匹配来做:
(1)二分图的最小顶点覆盖
最小顶点覆盖要求用最少的点(X或Y中都行),让每条边都至少和其中一个点关联。
Knoig定理:二分图的最小顶点覆盖数等于二分图的最大匹配数。

(2)DAG图的最小路径覆盖
用尽量少的不相交简单路径覆盖有向无环图(DAG)G的所有顶点,这就是DAG图的最小路径覆盖问题。
结论:DAG图的最小路径覆盖数 = 节点数(n)- 最大匹配数(m)

(3)二分图的最大独立集
最大独立集问题: 在N个点的图G中选出m个点,使这m个点两两之间没有边.求m最大值
结论:二分图的最大独立集数 = 节点数(n)— 最大匹配数(m)
邻接矩阵版:

主程序调用

int ans=0;
    for (i=1;i<=p;i++)
      {
        memset(used,false,sizeof(used));
        if (find(i))
          ans++;
      }

模板

bool find(int s)
{
    int k;
    for (k=1;k<=n;k++)
      if (f[s][k] && !used[k])
        {
            used[k]=true;
            if (part[k]==0 || find(part[k]))
              {
                part[k]=s;
                return true;
              }
        }
    return false;
}

next数组版:

模板

bool find(int s)
{
    int k;
    for (k=head[s];k;k=edge[k].next)
      if (!used[edge[k].to])
        {
           used[edge[k].to]=true;
           if (!part[edge[k].to] || find(part[edge[k].to]))
             {
               part[edge[k].to]=s;
               return true;
             }
        }
    return false;
}

建图

void add(int u,int v)
{
    cnt++;
    edge[cnt].next=head[u];
    head[u]=cnt;
    edge[cnt].to=v;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值