匈牙利算法——解决二分图匹配

二分图:

一种特殊的无向图,可以分为两个有关联边的集合(同一个集合内的点之间的点没有边)如图:
在这里插入图片描述
谈到二分图,不得不将二分图的匹配(最大匹配,最小没啥意义)
这就要谈到关于匈牙利算法,它也许不是最优化的,但是它是把这一类题目最基本思想展现出来的最简单最直接的算法。
其实这类似于贪心的过程:
我们如果如果有可以相互匹配的可以直接匹配,有不能匹配的点B递归地寻找那些理论上可以匹配但已经匹配的点A,尝试修改和A匹配的点的匹配,使B点尽可能地去实现匹配。
第一个蓝色点可以匹配:直接匹配
在这里插入图片描述
第二个蓝色点可以匹配:直接匹配
在这里插入图片描述
第三个蓝点不能匹配:寻找第二个红色点,观察它的匹配点能否修改。
在这里插入图片描述
第二个红色点的匹配点——第二个蓝色点不能直接匹配其他点(除了第二个红色点),去寻找另一个点(第一个红点)
在这里插入图片描述
发现第一个红点对于第一个蓝点可以匹配到第三个红点,以上的递归过程都可以实现。在这里插入图片描述
如果最后发现都不能匹配,那么之前递归的尝试修改的过程全都无效,回到第二个点匹配之后,且第三个点不能匹配。)

最后一个点直接匹配
在这里插入图片描述
主要代码:(其余部分按照题意编写)

const int maxn = 5e5+10;
int head[maxn],cnt = 0,be[maxn];
bool Vis[maxn];
struct Edge{//链式向前星,初始化head为-1。
    int to,next;
}edge[maxn];

void add_edge(int x,int y){
    edge[cnt]={y,head[x]};
    head[x] = cnt++;
}
bool dfs(int u){//每进行一个点的匹配是,要把Vis归0,保证所有点都可以尝试修改一次。
	for(int i = head[u];i >=0;i = edge[i].next)
    {
        int v = edge[i].to;
        if(!Vis[v]){ 
            Vis[v] = 1;
            if(!be[v]||dfs(be[v])){//没有匹配直接匹配,匹配了的,尝试修改匹配关系
                be[v] = u;
                return 1;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值