📜  检查给定图是否为二分图(1)

📅  最后修改于: 2023-12-03 15:40:35.826000             🧑  作者: Mango

检查给定图是否为二分图

什么是二分图?

二分图是一种特殊的图,其中所有节点可以分为两个不相交的集合,使得每条边的两个端点分别属于这两个集合。二分图也被称为双色图。

如何检查一个图是否为二分图?

可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来检查一个图是否为二分图。具体方法为:

  1. 将所有节点标记为未染色(或者标记为0表示未染色)。
  2. 选取一个未染色的节点,标记为染色1(或者标记为1)。
  3. 遍历该节点的所有邻居节点,对于每个邻居节点:
    • 如果该邻居节点未染色,将其标记为与当前节点不同的染色(例如,如果当前节点染色为1,则邻居节点染色为2,或者标记为-1)。
    • 如果该邻居节点已染色,判断其颜色是否与当前节点不同,如果颜色相同,则该图不是二分图,返回false;如果颜色不同,则跳过该节点。
  4. 重复步骤2和3,直到所有节点均被染色。
  5. 如果所有节点均被染色且满足二分图定义,则该图是二分图,返回true;否则,该图不是二分图,返回false。
采用BFS实现

以下是使用BFS实现的示例代码:

from collections import deque

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

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

以下是使用DFS实现的示例代码:

def is_bipartite_helper(graph, node, color):
    for neighbor in graph[node]:
        if color[neighbor] == 0:
            color[neighbor] = -color[node]
            if not is_bipartite_helper(graph, neighbor, color):
                return False
        elif color[neighbor] == color[node]:
            return False
    return True

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

    for i in range(n):
        if color[i] == 0:
            color[i] = 1
            if not is_bipartite_helper(graph, i, color):
                return False
    return True

以上两个示例代码都采用了一个数组color来记录每个节点的染色情况,其中0表示未染色,1表示染色1,-1表示染色2。不同的是,BFS的实现中使用了一个队列,而DFS的实现使用了递归。两个算法的时间复杂度均为O(n+m),其中n为节点数,m为边数。

总结

在实际应用中,判断一个图是否为二分图是非常有用的。例如,在交互式推荐系统中,可以将用户和商品分别看作一个集合,然后建立一个二分图来表示用户对商品的喜好程度,从而实现更精确的推荐。在实现二分图算法时,需要注意算法时间复杂度和空间复杂度,以及如何记录每个节点的染色情况。