首页 > 编程语言 >【有啥问啥】二分图(Bipartite Graph)算法原理详解

【有啥问啥】二分图(Bipartite Graph)算法原理详解

时间:2024-10-01 09:19:36浏览次数:9  
标签:二分 匹配 color Graph 详解 graph return Bipartite 顶点

二分图

二分图(Bipartite Graph)算法原理详解

引言

二分图(Bipartite Graph),又称二部图,是图论中的一个重要概念。在实际应用中,二分图模型经常用于解决如匹配问题、覆盖问题和独立集问题等。本文将详细解析二分图的基本概念、性质、判定方法,以及求解最大匹配问题的匈牙利算法,并探讨其在实际中的应用。

1. 基本概念

1.1 定义

设 G = ( V , E ) G=(V,E) G=(V,E)是一个无向图,如果顶点集 V V V可以分割为两个互不相交的子集 A A A和 B B B,且图中的每条边 ( i , j ) (i,j) (i,j)所关联的两个顶点 i i i和 j j j分别属于这两个不同的顶点集(即 i ∈ A , j ∈ B i \in A, j \in B i∈A,j∈B),则称图 G G G为一个二分图。

1.2 性质

  1. 无向图G为二分图的充分必要条件

    • G中至少包含两个顶点。
    • G中所有回路的长度均为偶数。
  2. 二分图的匹配

    • 设 G = < V , E > G=<V, E> G=<V,E>为二分图,如果 M ⊆ E M \subseteq E M⊆E,并且 M M M中任意两条边都没有公共端点(即没有边共用一个顶点),则称 M M M为 G G G的一个匹配。
  3. 最大匹配

    • 在所有匹配中,边数最多的匹配称为最大匹配。
  4. 完备匹配与完全匹配

    • 若 X X X中的所有顶点都是匹配 M M M中的端点,则称 M M M为 X X X的完备匹配。
    • 若 M M M既是 X X X-完备匹配又是 Y Y Y-完备匹配,则称 M M M为 G G G的完全匹配(也称完美匹配)。

2. 判定方法

2.1 原理

无向图 G G G为二分图的一个充要条件是 G G G中不存在奇圈(即所有回路的长度均为偶数)。这一性质是二分图判定的核心依据。

2.2 实现方法

  1. 染色法

    • 任意选择一个顶点并赋予颜色1(或称为红色),放入集合 U U U。
    • 将该顶点的所有未染色邻居顶点赋予颜色2(或称为蓝色),放入集合 V V V。
    • 依次对集合 V V V中的每个顶点重复上述过程,直到所有顶点都被染色或发现矛盾(即存在边连接的两个顶点颜色相同)。
    • 如果所有顶点都被成功染色,则图是二分图;否则,不是二分图。
  2. 代码实现(DFS版本):

    def dfs(graph, color, vertex, color_value):
     """
     Perform DFS to color the graph and check if it's bipartite.
     """
     color[vertex] = color_value
     for neighbor in range(len(graph)):
         if graph[vertex][neighbor]:
             if color[neighbor] == -1:
                 if not dfs(graph, color, neighbor, 1 - color_value):
                     return False
             elif color[neighbor] == color_value:
                 return False
     return True
    
     def is_bipartite(graph):
         """
         Check if the given graph is bipartite.
         """
         n = len(graph)
         if n == 0:
             return True  # An empty graph is trivially bipartite
         
         color = [-1] * n
         for i in range(n):
             if color[i] == -1:
                 if not dfs(graph, color, i, 0):
                     return False
         return True
    

3. 匈牙利算法求解最大匹配

3.1 原理

匈牙利算法通过不断寻找增广路(也称为增广轨或交错轨)来增加匹配中的边数,直到无法找到新的增广路为止,此时得到的匹配即为最大匹配。

3.2 实现步骤

  1. 初始化匹配集 M M M为空集。
  2. 对每个未匹配点 u u u,执行:
    • 从 u u u出发进行深度优先搜索(DFS),寻找一条增广路。
    • 如果找到增广路,则进行增广操作(即反转路径上边的匹配状态),并更新匹配集 M M M。
    • 重复上述过程,直到无法找到新的增广路为止。

3.3 代码实现

def dfs(graph, match, visited, u):
    """
    Depth-first search to find an augmenting path in the bipartite graph.
    
    :param graph: Adjacency matrix of the bipartite graph.
    :param match: Current matching state.
    :param visited: Visited nodes in the current DFS.
    :param u: Current node to start DFS from.
    :return: True if an augmenting path is found, False otherwise.
    """
    for v in range(len(graph[u])):
        if graph[u][v] and not visited[v]:
            visited[v] = True
            if match[v] == -1 or dfs(graph, match, visited, match[v]):
                match[v] = u
                return True
    return False

def hungarian(graph):
    """
    Hungarian algorithm to find the maximum matching in a bipartite graph.
    
    :param graph: Adjacency matrix of the bipartite graph.
    :return: The size of the maximum matching.
    """
    n = len(graph)
    match = [-1] * n  # Initialize match array with -1 (no matches initially)
    result = 0
    
    for u in range(n):
        visited = [False] * n  # Reset visited array for each new DFS
        if dfs(graph, match, visited, u):
            result += 1
    
    return result

4. 应用场景

二分图算法在很多实际场景中都有应用,例如:

  • 推荐系统:通过建立用户和物品的二分图,利用最大匹配算法为用户推荐最感兴趣的物品。
  • 任务分配:在生产或项目管理中,将任务与可执行者建立二分图关系,利用匹配算法优化资源分配。
  • 社交网络:分析社交网络中的用户与兴趣之间的关系,找到最佳的匹配组合。

总结

二分图算法是图论中的一项重要技术,其应用范围广泛。本文详细解析了二分图的基本概念、性质、判定方法,以及求解最大匹配的匈牙利算法。通过理解和应用这些算法,我们可以有效地解决许多实际问题。希望本文能为读者在二分图算法的学习和应用中提供帮助。

标签:二分,匹配,color,Graph,详解,graph,return,Bipartite,顶点
From: https://blog.csdn.net/mieshizhishou/article/details/142551977

相关文章

  • iperf3命令详解
    iperf3是一个用于网络性能测试的工具,主要用于测试带宽、延迟、丢包等网络相关指标。它支持TCP、UDP测试,还可以测量单向和双向流量。以下是iperf3的安装、基本使用方法和常见选项:1.安装iperf3在大多数Linux发行版上可以直接通过包管理器安装iperf3:Debian/Ubuntu:sud......
  • MegaCli64 命令详解
    MegaCli64是用于管理和监控基于LSI/Avago/BroadcomMegaRAID控制器的RAID阵列的命令行工具。可以使用它来查看硬RAID的健康状态和是否正在进行重建(rebuild)。1.查看RAID阵列的状态要检查RAID阵列的整体健康状态,可以运行以下命令:MegaCli64-LDInfo-Lall-aALL-LD......
  • P10280 Cowreography G
    P10280CowreographyG贪心本题的证明中涵盖了多种证明方法:分类讨论,交换两个,整体策略,堪称贪心证明之典范符号约定令\(s_x\)表示最初字符串的不同\(1\)位置,\(t_x\)表示最终字符串的不同\(1\)位置Theorem1:交换\(a_i,a_j(i>j,a_i\nea_j)\)的最优步数为\(\lceil\fr......
  • Redux详解
    Redux入门指南:简化状态管理的艺术在前端开发的广阔天地里,Redux作为一款预测性状态管理库,凭借其简洁的理念和强大的功能,在众多框架与库中脱颖而出,成为构建复杂应用的不二之选。本文将带你走进Redux的世界,通过实例代码,让你轻松掌握其核心概念与使用方法。一、Redux简介Red......
  • 流水线并行(Pipeline Parallelism)原理详解
    文章目录0.概览1.简单流水并行2.GPipe算法3.GPipe空间复杂度4.PipeDream算法5.总结参考0.概览数据并行(DataParallelism):在不同的GPU上运行同一批数据的不同子集;流水并行(PipelineParallelism):在不同的GPU上运行模型的不同层;模型并行(ModelParallelism):将......
  • 【科芯智雲城】详解MCU 产业,有什么成长潜力?
    MCU相当于一台小型电脑,因为它仅仅利用一块不到数平方平米大小的IC便能完成运算、存取、控制等功能,虽然运算能力较弱,但小体积、低耗能和低成本特性,让它广泛被应用在许多不需大量运算应用的设备中,小到额温枪、塑胶玩具、智能家电,大到机械手臂、电动车,都需要MCU作为控制核心......
  • 详解Java之继承与多态
    目录继承派生类和基类各部分执行顺序protected访问权限总结final关键字组合多态向上转型向下转型动态绑定静态绑定方法重载方法重写 super关键字super和this的对比在构造方法中调用重写方法继承继承是为了解决多个类具有一些相同的属性和方法而造成的代......
  • H.264编解码 - I/P/B帧详解
    一、概述在H.264编解码中,I/P/B帧是一种常见的帧类型。以下是它们的解释:I帧(关键帧):也称为关键帧,它是视频序列中的第一个帧或每个关键时刻的第一个帧。I帧是完整的、自包含的图像帧,不依赖于其他帧进行解码。它存储了关键时刻的完整图像信息。P帧(预测帧):P帧是依赖于之前的关......
  • 大数据-155 Apache Druid 架构与原理详解 数据存储 索引服务 压缩机制
    点一下关注吧!!!非常感谢!!持续更新!!!目前已经更新到了:Hadoop(已更完)HDFS(已更完)MapReduce(已更完)Hive(已更完)Flume(已更完)Sqoop(已更完)Zookeeper(已更完)HBase(已更完)Redis(已更完)Kafka(已更完)Spark(已更完)Flink(已更完)ClickHouse(已更完)Kudu(已更完)Druid(正在更新…)章节内容上节我们完成了如......
  • java:详解java编译命令和启动命令
    编译命令在Java开发过程中,编译Java源文件(通常以.java为扩展名)是不可或缺的一步。这一步骤是通过javac命令完成的,该命令是Java编译器(JavaCompiler)的命令行工具。编译后的代码会生成字节码文件,这些文件以.class为扩展名,并可在Java虚拟机(JVM)上运行。基本语法......