浅谈匈牙利算法

题目链接

二分图最大匹配的模板。

对于二分图

我们称,一个图中,当且仅当其没有奇环时,是一个二分图。

那么,最大二分图匹配就是:

给定二分图,现在要选出一些边,使得与每一个点相连的边最多选出一条,求最多选出的边数。

当所有边都被匹配上时,称之为一个完美的二分图匹配。

来一个例题吧:

 

从前有a个男生和b个女生,有一些男女之间有互相喜欢的关系,现在它们想要两两配对,怎样配对才能让配成的对数尽可能多?

这就是上面那一句话啊。

我们来模拟一下匈牙利算法的流程。

我们规定:第一天,每个男生按顺序取找女生表白。

其中,每个女生每天只能被表白一次。

对于找到的女生,如果她没有对象,就暂时接受。

如果有,就让她原来的对象尝试去找新的女生表白。

如果他成功的,她就抛弃他,去接受这个新的。

否则,就拒绝这个新来的。

例如:

1,2.3是男生,ABC是女生。

引入老师的话:

第一天,1向A表白,A答应了。

第二天,2向A表白,A说“可是我已经答应1了耶,要不你去跟他商量商量?”于是2来到1的家里,谁知1拔出手枪指向2喊“滚!”

第三天,2向B表白,B答应了。

第四天,3向B表白,开着坦克隆隆地推到2家门口……

第五天,2向C表白……

匈牙利真是一个好地方!

就这样,这就是匈牙利(神奇的地方)算法!

于是,我们可以这样实现:

用临接表存边,暴力枚举A图中的点,再暴力枚举B图中的点。

令vis数组表示x点是否已经访问过,match表示x所匹配的点。

若已经访问过,pass.

没有的话,判断:

当它没有匹配或者是它匹配的点换人了,它就要尝试去换了。

这时返回true。

如果一直没有匹配到,就返回false好了。

把每次的结果加起来,求出A图中所有点的匹配数,即为答案。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int match[500000],vis[500000];
int n,m,E,ans,head[500000],tot;
struct node{
    int nxt,to;
}e[500000];
inline void add(int x,int y){
    e[++tot].nxt=head[x];
    e[tot].to=y;
    head[x]=tot;
}
void read(int &x) {
    x=0;
    int f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9') {
        if (ch=='-')f=-f;
        ch=getchar();
    }while (ch>='0'&&ch<='9') {
        x=x*10+ch-48;
        ch=getchar();
    }x*=f;
}
bool dfs(int x){
    for(int i=head[x];i;i=e[i].nxt){
        int j=e[i].to;
        if(vis[j])continue;
        vis[j]=1;
        if(!match[j]||dfs(match[j])){
            match[j]=x;
            return true;
        }
    }return false;
}
void work(){
    for(int i=1;i<=n;++i){
        memset(vis,0,sizeof(vis));
        ans+=dfs(i);
    }
}
int main(){
    read(n);read(m);read(E);
    for(int i=1;i<=E;++i){
        int x,y;
        read(x);read(y);
        if(x>=1&&x<=n&&y>=1&&y<=m){add(x,y);}
    }
    work();
    printf("%d\n",ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/h-lka/p/11256429.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
匈牙利算法,也称为二分图最大匹配算法,是一种解决二分图最大匹配问题的经典算法。它的目标是在一个二分图中找到最大的匹配数,即找到最大的能够互相配对的节点对数。 Python是一种高级编程语言,具有简洁、易读、易学的特点,广泛应用于各个领域。在Python中,我们可以使用网络流算法库或者自己实现匈牙利算法来解决二分图最大匹配问题。 以下是匈牙利算法的基本思想和步骤: 1. 初始化一个空的匹配集合。 2. 对于每个未匹配的左侧节点,尝试将其与一个未匹配的右侧节点进行匹配。 3. 如果右侧节点未被匹配,或者已被匹配但可以通过其他路径重新匹配,那么将左侧节点与右侧节点进行匹配,并将右侧节点标记为已匹配。 4. 如果右侧节点已被匹配且无法重新匹配,那么尝试将右侧节点的当前匹配节点重新匹配到其他未匹配的左侧节点。 5. 重复步骤3和步骤4,直到无法找到更多的匹配。 在Python中,可以使用networkx库来实现匈牙利算法。以下是一个使用networkx库解决二分图最大匹配问题的示例代码: ```python import networkx as nx # 创建一个空的二分图 G = nx.Graph() # 添加左侧节点 G.add_nodes_from(['A', 'B', 'C']) # 添加右侧节点 G.add_nodes_from([1, 2, 3]) # 添加边 G.add_edges_from([('A', 1), ('A', 2), ('B', 2), ('C', 3)]) # 使用匈牙利算法求解最大匹配 matching = nx.bipartite.maximum_matching(G) # 输出最大匹配结果 print(matching) ``` 以上代码中,我们首先创建了一个空的二分图,并添加了左侧节点和右侧节点。然后,我们使用`nx.bipartite.maximum_matching`函数来求解最大匹配,并将结果存储在`matching`变量中。最后,我们输出最大匹配结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值