二分图:从定义到判定与匹配的完整指南

1. 什么是二分图

二分图(Bipartite Graph),又称二部图,是图论中的一类特殊图。它的定义是:设图 G = (V, E) 是一个无向图,如果顶点集 V 可以划分为两个互不相交的子集 A 和 B,使得图中每条边的两个端点分别属于 A 和 B,则称图 G 为二分图。

换句话说,二分图中的所有边都连接着两个不同集合中的顶点,同一个集合内部的顶点之间不存在边。这种结构在现实世界中非常常见,例如:

  • 学生选课:学生和课程分别构成两个集合,边表示选课关系。
  • 任务分配:工人和任务构成两个集合,边表示工人能胜任该任务。
  • 社交网络:用户和兴趣标签构成两个集合,边表示用户关注该标签。

二分图之所以重要,是因为许多实际问题都可以抽象为二分图模型,进而利用图论算法高效求解。

2. 二分图的性质与判定

判断一个图是否为二分图,最常用的方法是染色法。其核心思想是:从任意一个顶点出发,将其染成一种颜色(如红色),然后将其所有邻接顶点染成另一种颜色(如蓝色),再依次对邻接顶点的邻接顶点染色。如果在染色过程中,某个顶点已经被染成与当前应染颜色不同的颜色,则说明图中存在奇数环,该图不是二分图。

染色法通常借助广度优先搜索(BFS)或深度优先搜索(DFS)实现,时间复杂度为 O(V + E),其中 V 是顶点数,E 是边数。

二分图有一个重要性质:一个图是二分图,当且仅当它不包含奇数长度的环。这个性质是染色法正确性的理论基础。

from collections import deque

def is_bipartite(graph):
    n = len(graph)
    color = [-1] * n  # -1 表示未染色,0 和 1 表示两种颜色

    for i in range(n):
        if color[i] == -1:
            color[i] = 0
            queue = deque([i])
            while queue:
                node = queue.popleft()
                for neighbor in graph[node]:
                    if color[neighbor] == -1:
                        color[neighbor] = 1 - color[node]
                        queue.append(neighbor)
                    elif color[neighbor] == color[node]:
                        return False
    return True

3. 二分图的最大匹配

在二分图中,匹配是指一组边,其中任意两条边都没有公共顶点。最大匹配则是包含边数最多的匹配。求解二分图最大匹配的经典算法是匈牙利算法(Hungarian Algorithm),其时间复杂度为 O(V × E)。

匈牙利算法的核心思想是增广路径:从左侧集合的一个未匹配顶点出发,寻找一条交替经过未匹配边和已匹配边的路径,如果路径的终点是右侧集合的未匹配顶点,则沿着该路径翻转匹配状态,即可使匹配数加一。重复这一过程,直到找不到增广路径为止。

def hungarian(graph, n_left, n_right):
    match_right = [-1] * n_right  # 右侧顶点匹配的左侧顶点编号

    def dfs(u, visited):
        for v in graph[u]:
            if not visited[v]:
                visited[v] = True
                if match_right[v] == -1 or dfs(match_right[v], visited):
                    match_right[v] = u
                    return True
        return False

    result = 0
    for u in range(n_left):
        visited = [False] * n_right
        if dfs(u, visited):
            result += 1
    return result

4. 二分图的应用场景

二分图及其匹配算法在工程实践中有着广泛的应用,以下是几个典型场景:

  • 任务分配问题:将 n 个任务分配给 m 个工人,每个工人只能完成部分任务,目标是让尽可能多的任务被完成。
  • 课程安排:将课程安排到时间段,避免同一学生同时上多门课。
  • 推荐系统:将用户与物品建模为二分图,通过匹配或图嵌入算法进行个性化推荐。
  • 棋盘覆盖问题:用多米诺骨牌覆盖棋盘上的特定格子,可转化为二分图最大匹配问题。

此外,二分图还与最小点覆盖最大独立集等经典问题紧密相关。根据柯尼希定理(König's Theorem),在二分图中,最大匹配数等于最小点覆盖数,这一结论在算法设计中经常被用来相互转化问题。

5. 总结

二分图是图论中一类结构优美且应用广泛的图。本文从定义出发,介绍了二分图的染色判定方法、匈牙利算法求解最大匹配,以及典型的应用场景。掌握二分图模型,能够帮助我们在面对许多实际优化问题时,快速找到高效的算法路径。

建议读者在理解算法原理后,动手实现一遍染色法和匈牙利算法,并结合 LeetCode 或算法竞赛中的相关题目进行练习,以加深对二分图的理解。

下载代码方式:https://pan.quark.cn/s/2f5b5de24682 课程设计开题报告文档总共包含21页,共计8044字,其源代码构成整个工程文件(使用VS2019环境)。 <实验课题>部分详细记录了每位学生的具体资料,包括学号、姓名、性别、家庭住址、联系电话,以及语文、数学、外语三门的单科成绩、考试平均成绩、考试名次、同学互评成绩、品德评价、任课教师评分和综合测评总分和名次。 <功能要求>部分具体阐述了如下功能: 1、学生信息管理: (1) 学生信息的录入:需要输入学号、姓名、性别、家庭住址、联系电话,并按照学号由小到大的顺序将信息存储至文件中。 建议:学生信息可先暂存于数组中,完成排序后再写入文件。 (2) 学生信息的修改删除:允许修改除学号以外的其他信息,删除时需输入学生学号,系统将读取该学生的信息,并要求用户确认以决定是否执行删除操作。 2、学生数据管理: (1) 学生成绩的录入:按照考试科目录入学生成绩,并根据公式:考试成绩=(语文成绩+数学成绩+外语成绩)/3,计算得出学生记录后写入一个文件中。 (2) 学生综合测评数据的录入计算:输入学生测评数据,计算综合测评总分及名次。 提示:综合测评总分=考试成绩*0.6+同学互评成绩*0.1+品德成绩*0.1+任课教师评分*0.2。 3、菜单系统的设计:实现功能选项的选择; 4、数据同步文件读取:学生的信息录入、修改、删除操作均可实时同步至文件中,系统亦可通过读取已记录的文件来获取数据。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值