二部图和匈牙利算法

二部图最大匹配--匈牙利算法 二分图的最大匹配、完美匹配和匈牙利算法 这篇文章讲无权二分图(unweighted bipartite graph)的最大匹配(maximum matching)和完美匹配(perfect matching),以及用于求解匹配的匈牙利算法(Hungarian Algorithm);不讲带权二分图的最佳匹配。 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是 阅读详情

二部图

二部图的定义:设 G G G是一个图,若 V ( G ) V(G) V(G)有一个划分: V ( G ) = V 1 ⋃ V 2 V(G)=V_1 \bigcup V_2 V(G)=V1​⋃V2​,使得< V 1 V_1 V1​>< V 2 V_2 V2​>都是空图,那么称图 G G G是一个双图,或二部图,或二分图。
简单来说,就是在图中切上一刀,就能使所有点变成孤立的,如下图沿着红线切一刀。在这里插入图片描述
判定二分图一般使用标号法,即将一个顶点和与之相邻的顶点标为不同,若此过程可以一直进行下去,则为二分图。
标号法
代码判定
下面给出深搜的判定,广搜当然也可以(只要维护一个队列)。

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
const int N = 505;
int m,n;
int color[N];
int edge[N][N];
 
bool dfs(int v, int c){
    color[v] = c;    //将当前顶点涂色
    for(int i = 0; i < n; i++){    //遍历所有相邻顶点,即连着的点
        if(edge[v][i] == 1){    //如果顶点存在
            if(color[i] == c)    //如果颜色重复,就返回false
                return false;
            if(color[i] == 0 && !dfs(i,-c))    //如果还未涂色,就染上相反的颜色-c,并dfs这个顶点,进入下一层
                return false;   //返回false
        }
    }
    return true;   //如果所有顶点涂完色,并且没有出现同色的相邻顶点,就返回true
}
 
void solve(){
    for(int i = 0; i < n; i++){//对每一点都要判定,因为图可能不是连通的
        if(color[i] == 0){
            if(!dfs(i, 1)){
                printf("NOT BICOLORABLE.\n");
                return;
            }
        }
    }
    printf("BICOLORABLE.\n");
}
 
int main(){
    int u,v;
    while(cin >> n >> m){
        memset(color, 0, sizeof(color));
        memset(edge, 0, sizeof(edge));
        for(int i = 0; i < m; i++){
            cin >> u >> v;    //因为是无向图,所以要往两个方向添加边
            edge[u][v] = 1;    //正着添加
            edge[v][u] = 1;    //反着添加
        }
        solve();
    }
    return 0;
}

匈牙利算法

基本概念:

  • 图 G G G的一个匹配是由一组没有公共端点的不是圈的边构成的集合。
    如图就是之前的图的一个匹配。可知:1. 匹配是边的集合;2. 在该集合中,任意两条边不能有共同的顶点。
    在这里插入图片描述
    就好像参加相亲节目,在不考虑同性恋的情况下,要给匹配合适的对象,有边代表男女嘉宾互有好感。所谓最大匹配,就是节目效果要达到最好,需要尽可能多的互有好感的人配对。
    匈牙利算法可以解决二部图上最大匹配问题。该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法。
    ——上面的描述看起来很绕而且有很多概念对不对,下面我们直观地感受一下算法的过程。你会发现,其实我们做的是月老的活。
    首先,我们这个相亲节目在先来后到的基础上很照顾后来的人,会优先考虑后来人的需求,但同时也不能拆散先来的人让他遗憾离场。
    在这里插入图片描述
    现在有三个男嘉宾和三个女嘉宾,男嘉宾有选择权。先从一号男嘉宾开始,他选择了1号女嘉宾,3号女嘉宾成为了他的备胎。
    在这里插入图片描述
    2号男嘉宾来了,他说我也要1号女嘉宾,1号男嘉宾你往后稍稍。节目组这时候劝说1号男嘉宾,哎,你还有3号备胎,你把1号女嘉宾让给2号男嘉宾吧!
    1号一想也是,不如顺便送个人情,于是他换成了3号女嘉宾,2号男嘉宾如愿匹配了1号女嘉宾,并把2号女嘉宾作为了自己的备胎。
    在这里插入图片描述
    这时3号男嘉宾上场,他说我为1号而来!我只要1号!节目组的老好人们又去劝说正和1号牵线的2号男嘉宾。当然2号男嘉宾也同意了,毕竟他还有2号备胎嘛!
    于是本期节目皆大欢喜,大家都牵手成功~
    在这里插入图片描述
    ——这个匹配即是最大匹配,也是完美匹配。
    但是有没有失败而归的情况呢?也是有的:
    假如是这样一张图:
    在这里插入图片描述
    1号2号男嘉宾已经进行了协调和选择:
    在这里插入图片描述
    这时候3号男嘉宾来了,还是非1号不可。节目组劝说2号,2号说我要看看备胎在不在,于是询问3号女嘉宾。
    3号女嘉宾说我得问问1号男嘉宾还有没有备胎。(这是一个递归的过程)
    1号男嘉宾:你就是我的备胎!我的原配已经给2号了!
    于是3号女嘉宾告诉2号,对不起啊,1号没有选择了,我也不当你的备胎了。
    于是2号男嘉宾告诉节目组,对不起啊,我也没有选择了,我不让。
    节目组当然尊重他们的选择,毕竟不能强行拆散,只为了3号男嘉宾。所以节目组告诉3号男嘉宾,对不起啊,你没有牵手成功。
    匹配结果如下:
    在这里插入图片描述
    这是一个最大匹配(满足多数人的需求),但不是完美匹配。

实现代码

题例:POJ1274
大意:有n个槽和m头牛,牛只在特定的几个槽才产奶,求最多几头牛可以产奶。

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 220;
int n,m;
int mark[maxn];
int match[maxn];
int maze[maxn][maxn];
int ans;

bool Find(int x){
    for(int i = 1;i <= m;++i){
        if(maze[x][i] && !mark[i]){  //如果牛在这里产奶且槽还没问过
            mark[i] = 1;
            if(match[i] == 0 || Find(match[i])){//如果没分配或者分配了但是可以找到别的给那个对象
                match[i] = x;
                return true;
            }
        }
    }
    return false;
}

void slove(){
    memset(match,0,sizeof(match));
    ans = 0;
    for(int i = 1; i <= n;++i){
        memset(mark,0,sizeof(mark));
        if(Find(i))ans++;
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m)){
        for(int i = 1; i <= n;++i)
            for(int j = 1; j <= m;++j)
            maze[i][j] = 0;

        for(int i = 1; i <= n;++i){
            int x;
            scanf("%d",&x);
            for(int j = 1; j <= x;++j){
                    int tmp;
                scanf("%d",&tmp);
                maze[i][tmp] = 1;
            }
        }
        slove();
        printf("%d\n",ans);
    }
    return 0;
}

最大匹配数=最小点覆盖数。因此最小点覆盖也可以转化为最大匹配问题。
一些例题:
POJ1325
POJ3692(需要建补图,是最大独立集的问题)
POJ1469
POJ3041*这个问题的转化比较巧妙了,题目大意是一个网格里有一些障碍物,一发炮弹可以清除同一行或者同一列的障碍物,问最少开几枪。转化障碍物坐标,行坐标为一个集合,列坐标为一个集合,障碍物的坐标连线,使用匈牙利算法。
(大概是考虑在同一行则行坐标相等,尽可能多的为不同的行坐标都能匹配到列坐标。。。)
应用可以参考这篇博客:匈牙利算法—介绍与基本用途

微信小游戏审核避坑指南:如何一次性通过微信审核(附最新审核要求) 本文详细解析微信小游戏审核全流程,提供从开发到上线的关键策略,帮助开发者一次性通过审核。涵盖合规性自查、材料优化、开发环境配置、版本管理、审核材料填写技巧等核心内容,并附最新审核要求和常见驳回问题解决方案,显著提升审核通过率。 阅读详情

相关推荐

EEGnet模型论文讲解(画图详解三种卷积层操作)

我录了一个讲解视频:https://www.bilibili.com/video/BV1si4y1s7g7/ 目录 一、整体介绍 二、梳理激活函数 三、图解三种卷积层 (核心内容) 四、总结 一、整体介绍 EEGnet是为专门一般的脑电图识别任务而设计的通用且紧凑的卷积神经网络。(设计思路借鉴了MobileNet) 下图是EEGnet的整体结构图,只有三个卷积模块,重点是depthwise conv 和separable conv这两个卷积模块。 表格表明了EEGnet的...

Amigo_1997的博客 2万+

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

二分图最大匹配(一)、二分图的介绍1、定义2、充要条件(二)、二分图的匹配1、二分图的最大匹配2、增广路径3、匈牙利算法(1)、复杂度 (一)、二分图的介绍 1、定义 二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点 i 和 j 分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 2、充要条件 无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的

hahahahahaha5的博客 1万+

GPD源码分析

gpd使用示例 先看下面一段代码,为标准gpd算法的使用方法,可以看到输入为点云,cloud_camera_; 输入:std::unique_ptr<gpd::util::Cloud> cloud_camera_ 输出: std::vector<std::unique_ptr<gpd::candidate::Hand>> grasps; // detect grasp poses gpd对象:std::unique_ptr<gpd::GraspDetect.

weixin_41003113的博客 2332

二分图之匈牙利算法

主要内容:二分图的最大匹配,完美匹配,最小路径覆盖数,匈牙利算法 二分图相关概念1.二分图:把一个图的顶点划分为两个不相交集U和V,使每一条边都分别连接U、V中的顶点。 无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。即是说,一个图要么没有环,要么有偶数边的环。所以二分图的另一个定义为:不含有「含奇数条边的环」的图。 2.匹配:在图论中,一个「匹配」(match

ROOM 862

Android13 AudioFlinger混音流程全解析:从prepareTracks_l到threadLoop_write的底层实现

本文深入解析Android13 AudioFlinger混音流程,从prepareTracks_l到threadLoop_write的底层实现。详细剖析MixerThread的核心工作循环,包括音轨预处理、混音算法执行及硬件写入机制,帮助开发者优化音频性能并处理多音轨场景。

tea88的博客 1130

Win11下WSL2安装Ubuntu22.04避坑指南:从镜像源到C++环境配置

本文提供了一份详细的Win11下WSL2安装Ubuntu22.04的实战避坑指南。内容涵盖从WSL2核心安装、自定义安装路径,到更换国内镜像源以解决更新缓慢问题,并一站式配置完整的C++开发环境(包括GCC、CMake、vcpkg等),最后分享提升开发体验的进阶技巧,助你在Windows上打造高效的Linux开发工作站。

weixin_29260291的博客 562

二部图------KM算法、匈牙利算法

二分图的概念 二分图又称作二部图,是图论中的一种特殊模型。  设G=(V, E)是一个无向图。如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y中,则称图G为二分图。  二分图的性质 定理:当且仅当无向图G的每一个回路的次数均是偶数时,G才是一个二分图。如果无回路,相当于任一回路的次数为0,故也视为二分图。 二分图匹配 给定一个二分图G,在...

wang_gongzi的博客 1958

深度强化学习系列(13): 策略梯度(Policy Gradient)

对于DQN来说使用一个网络直接逼近了值函数,最后取得了非常不错的效果, 但是对于一些连续性控制或者动作空间特别大的环境来说,很难全部计算所有的值函数来得到最好的策略,那么直接计算策略的方法就别提出来了。 回顾一下前面几篇,所谓的策略,其实就是状态到动作的映射数学表达为 π:s→aπ:s→a\pi : s \to a, 我们用ττ\tau 表示状态s到最后一个状态的一个序列,表示为: τ:st...

深度强化学习(DeepRL)探索博客 4641

二分图匹配-匈牙利算法

二分图概述 所谓二分图,就是我们可以将图中所有的点分为A、B两个集合,从而使得集合内部任意两个点都不直接相连。 二分图适用于解决一种类似于婚姻匹配的问题,即如果A-B匹配,那么A就不能在和C匹配,即便他们之间有好感。 最大匹配 二分图的最大匹配即需要给出一种分配策略,使得产生尽可能多的对(就是撮合最多多少对情侣)。 匈牙利算法是一个用于解决该类问题的标准算法之一,核心想法是让路:假设你(就是红娘)当前想撮合Bi与Gk,但是Gk已经有了对象Bj,此时红娘就和Bj交涉能否让Bj尝试换一个对象.

The Shawshank Redemption 6543

mbedtls | 01 - 移植mbedtls库到STM32的两种方法

一、mbedtls 开源库 1. mbedtls是什么 Mbed TLS是一个开源、可移植、易于使用、代码可读性高的SSL库。可实现加密原语,X.509证书操作以及SSL / TLS和 DTLS 协议,它的代码占用空间小,非常适合用于嵌入式系统。 mbedtls遵循 Apache 2.0 开源许可协议,目前由 TrustedFirmware 维护(Linaro主持的一个治理开放社区项目),在Github上已收获 2.6k star,目前Github上发布的最新版本为 2.24.0 版本,开源仓库地址为:

Mculover666的博客(嵌入式) 1万+

【OpenClaw企业级智能体实战】第04篇:OpenClaw成本优化实战——Token消耗降96%!claude-mem+OpenViking从入门到精通

OpenClaw作为企业级智能体框架,凭借强大的自动化能力成为企业数字化转型的热门工具,但原生机制导致的上下文冗余问题,让众多用户面临“Token消耗失控”的困境——单周账单数千元的案例屡见不鲜。本文基于阿里云实测数据与开源工具官方文档,先深度拆解OpenClaw成本黑洞的核心成因(记忆碎片化、Token指数级膨胀),再系统讲解两款核心优化工具(claude-mem单Agent记忆管理、OpenViking多Agent集群底座)的底层原理、算法架构与实现逻辑,提供从环境搭建、工具集成、参数调优到安全部署

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 703

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

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法。 基本原则就是在原有匹配(最开始的按优先顺序匹配)基础上重新分配,看是否可以添加一个新的匹配。 预备知识 我们需要了解一下图论的一些知识。 1 无向图 边没有方向的图称为无向图...

Young_Fan 1万+

本地玩转AI还得靠这个,SillyTavern(酒馆)到底有多强?

SillyTavern是一款本地运行的LLM交互前端,支持文本生成、图像生成、语音合成等功能。它最初是TavernAI的分支,现已独立开发,社区活跃,功能更新频繁。SillyTavern通过前端UI和插件系统连接各种大模型后端,如OpenAI、KoboldAI等,用户可以在本地创建“虚拟酒馆”与各种角色对话。其功能亮点包括角色卡、角色记忆、世界设定、多人聊天室、自定义UI和行为脚本、插件扩展支持等。SillyTavern适合AI创作用户、AI工程师、LLM爱好者和AIGC创作者。它有两个维护分支:relea

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 8033

使用matlab对二部图进行匹配(匈牙利算法)

使用matlab应用匈牙利算法对二部图进行匹配。 算法的代码主体来自知乎用户洪九(李戈)的专栏文章策略算法工程师之路-图优化算法(一)(二分图&最小费用最大流) 具体算法思想文章里和其它地方都有,不在这里赘述。主要通过例子来说明算法具体运行过程中所作的操作对匈牙利算法进行说明。 首先对于如下图的一个二部图 左侧有6个点,右侧有7个点,点之间的边都画出来了。 第一步:对x1x_1x1​进行匹配,找到它的第一个可匹配项y1y_1y1​,发现此时y1y_1y1​还未被匹配,因此将x1x_1x1​和y1y

john_xia的博客 4556

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

匈牙利算法求二部图的最大匹配

匈牙利算法求二部图的最大匹配(含详细算法步骤) 1.概念 (1)二部图(偶图) (2)匹配 (4)饱和 (5)可增广路 (6)匈牙利算法 2.数学语言表示匈牙利算法 (1)算法流程 (2)举例

weixin_69884785的博客 2039

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

二部图匹配-匈牙利算法-KM算法

int M, N; //M, N分别表示左、右侧集合的元素数量 int Map[MAXM][MAXN]; //邻接矩阵存图 int p[MAXN]; //记录当前右侧元素所对应的左侧元素 bool vis[MAXN]; //记录右侧元素是否已被访问过 bool match(int i) { for (int j = 1; j <= N; ++j) if (Map[i][j] && !vis[j]) //有边且未访.

己亥孟陬 900

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【数学与算法】二部图、匈牙利匹配、稳定婚配

14.1 二部图 广度优先搜索 广度优先,可以使用队列来操作,依次遍历节点,首先遍历节点A,判断节点A是否遍历过,如果节点A没有遍历过,就把节点A添加进队列。然后取出队列中的第一个元素A,对于和节点A连接的某节点B和节点C等,把节点B和c进行标记(标记就是根据题目的具体要求进行操作,即你的目的是什么你就干什么),并且如果节点B和c没有遍历过,那么把节点B和C添加进队列。然后再取出队列中的第一个元素,就是节点B,遍历到了B节点,再对和B节点连接的节点D进行标记,并且判断D是否遍历过,没有遍历过的话就添加到队列

u011754972的博客 1330

Python-匈牙利算法求二部图的最大匹配

hyi asc from collections import defaultdict import time class Graph: def __init__(self,n,s,t,l) -> None: self.S,self.T,self.L=s,t,l # 源s,汇t self.edge=defaultdict(list) # 边集 self.ver_high=[0 for i in range(n)] # 每个顶点的高度

qq_37217601的博客 898

记录下HDU-2063(二部图-匈牙利算法)

二部图例题HDU-2063(匈牙利算法) 二部图基本概念: 二部图:一个图中的所有点能够被划分为两个集合,图中的所有边都跨越了集合的边界。(例如:一群人以男女区分为两部分,一些男生喜欢一些女生,一些女生喜欢一些男生,这些男女生和这些喜欢的情况可以称作二部图) 匹配:匹配是一组边的集合,其中任意两边都没有公共点。(若彼此喜欢男女生能够在一起,某一情况下所有这种能够在一起的关系称为匹配,这一情况下在一起的关系就称为匹配边,原本喜欢但是没有在一起的就称为未匹配边) 最大匹配:所有匹配中,边数最多的一个匹配关系。

weixin_47350566的博客 390

二部图最大匹配问题的求解 匈牙利算法

#define MAXN 10 //MAXN为表示X集合和Y集合顶点个数最大值的符号常量 int nx, ny; //X和Y集合中顶点的个数 int g[MAXN][MAXN]; //邻接矩阵,g[i][j]为1表示Xi和Yj有边相连 int cx[MAXN] , cy[MAXN]; //cx[i]表示最终求得的最大匹配中与Xi匹配的Y顶...

Phoebe_Wu2016的博客 333

【二部图匹配问题--匈牙利算法】

最近的研究需要,学习二部图的匹配问题,自然就学习了匈牙利算法,虽然跟我目前要解决的问题--多对多加权双边匹配问题有许多不同,但算是二部图匹配的入门算法。 在网上看到不错的博文,借来学习。 http://blog.youkuaiyun.com/pi9nc/article/details/11848327该博文基本概念讲得不错匈牙利算法(二部图匹配、已知各个节点的偏好集合、无权匹配、一对一、最大化所有匹配边数...

weixin_30412167的博客 343

【PTA数据结构 | C语言版】求解二部图最大匹配的匈牙利算法

请编写程序,实现求解无权二部图最大匹配的匈牙利算法。输入格式:输入首先在第一行给出 3 个正整数,依次为二部图 G=(U∪V,E) 中 U 点集顶点数、V 点集顶点数(均不超过 100)和边数 m。随后 m 行,每行给出一条连接 U 点集顶点和 V 点集顶点的边,格式为 u v,其中 u 属于 U,v 属于 V。两个点集的顶点编号均从 0 开始。同行数字间以一个空格分隔。输出格式:在一行中输出 最大匹配值 = x,其中 x 为最大匹配数。

等风来 682

二部图匹配匈牙利算法(转)

这种题目一般是一个东东对应着另外的东东,一般是多对多的关系,这就形成了一个二部图,问这个二部图最大的匹配数是多少(就是形成一个一对一的关系,求最大的一对一关系的个数)。模板:#define MAXN 310int nx,ny,mat[MAXN][MAXN],fy[MAXN],matx[MAXN],maty[MAXN];int path(int u) {int v;for (v=

1635

二部图-匈牙利算法实现

两篇参考网址 http://blog.youkuaiyun.com/dark_scope/article/details/8880547 相亲举例http://m.blog.youkuaiyun.com/blog/fyxz1314/37651567 偏公式 增广路径:非匹配边->匹配边->非匹配边组成的路径递归:将之前匹配边的女生赋给新的男生,之前匹配边的男生重新找到心仪的女生,如此递归。 #include

相门码农的专栏 732

二部图 匈牙利算法

匈牙利算法:http://www.renfei.org/blog/bipartite-matching.html  http://www.codeceo.com/article/bgraph-match-algorithm.html http://dsqiu.iteye.com/blog/1689505 一道练习题: http://blog.sina.com.cn/s/blog_ac

lnlnlnying的博客 482
上一篇: 最小树形图(有向图的最小生成树)
下一篇: 打印月历
softwareX4
博客等级 码龄9年 21粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值