Python中的二分图

2025 年 1 月 5 日 | 11 分钟阅读

在本教程中,我们将学习二分图以及检查给定图是否为二分图的方法。

二分图是指可以将其顶点分成两个独立集合的图。设这两个集合为 S1 和 S2。这两个集合将包含元素 s1 和 s2,其中 s1 和 s2 通过图中的边相连。因此,元素 (s1, s2) 是将顶点从集合 S1 连接到第二个集合的顶点 s2 的边。此外,一个集合中的元素不能相互连接。

如果可以使用两种颜色为图的顶点着色,并且所有相邻节点的对都具有不同的颜色,则称该图为二分图。

如果可以使用两种颜色进行图着色,使得集合中的顶点着相同的颜色,则二分图是可能的。请注意,具有偶数环的循环图可以使用两种颜色进行着色。例如,请参见下图。

具有奇数环的循环图无法使用两种颜色进行着色。

检查图是否为二分图的算法

检查图是否为二分图的简单方法是为每个节点着色。我们将使用两种颜色,并为每个节点着上替代颜色。如果我们能够为每个节点着色,并且没有相邻节点具有相同的颜色,那么该图就是二分图;否则,它就不是。

我们将为当前顶点着色,并为其邻居着上替代颜色。这样,我们将遍历每个顶点并为节点着色。如果在任何时候发现父节点和相邻节点具有相同的颜色,我们将停止算法并打印出给定图不是二分图。

代码

输出

The given graph is not a Bipartite graph

时间复杂度:我们正在遍历大小为 V * V 的邻接矩阵的元素。在最坏的情况下,我们将遍历矩阵的每个元素;因此,时间复杂度为 O(V * V)。

空间复杂度:我们创建了一个队列和一个数组来存储顶点的颜色。因此,空间复杂度为 O(V)。

我们创建的算法仅适用于单连通图。如果图有多个组件,则只会遍历一个组件。我们需要修改代码,使其适用于多个组件。我们将从源 0 开始,并且我们知道连通的节点将被访问。没有边的图是二分图。这是因为,在二分图中,单个集合中的节点不应与其自身相连。

我们将修改代码以处理这些情况。将为图的每个组件调用 BFS 遍历,直到访问完图的所有节点。

代码

输出

The given graph is not a Bipartite graph

时间复杂度:我们遍历总的顶点和边数。因此,时间复杂度为 O(V + E)。

空间复杂度:我们创建了一个数组来存储已访问的节点。因此,空间复杂度为 O(V)。

在上面的示例中,图由邻接矩阵表示。如果图由邻接列表表示怎么办?因此,现在我们将看到邻接列表上的 BFS 遍历。此算法的时间复杂度将为 O(V + E)。这是一个通用算法,适用于单连通图和多连通图。

代码

输出

The graph is a bipartite graph

时间复杂度:此方法的时间复杂度与上一个算法相同,即 O(V * V)。

空间复杂度:我们创建了一个数组来存储已访问的节点。因此,空间复杂度为 O(V)。

让我们看看如果给定图的邻接列表,如何检查图是否为二分图

代码

输出

The graph is a bipartite graph

时间复杂度:如果以邻接列表的形式遍历图,时间复杂度将降低到 O(V + E),其中 V 是图中的顶点数,E 是图中的边数。

空间复杂度:我们创建了一个数组来存储已访问的节点。因此,空间复杂度为 O(V)。