【Leetcode刷题】判断二分图

https://leetcode-cn.com/problems/is-graph-bipartite/

动态维护A、B集合算法

class Solution(object):
    def isBipartite(self, graph):
        """
        :type graph: List[List[int]]
        :rtype: bool
        """
        # 由于每一条边的两个节点要来自不同的子集
        # 那么设节点1属于集合A,节点1邻接的节点应当属于集合B
        # 维护集合A、集合B。遍历图的节点并更新两个集合
        # 一旦检测到某个节点与其邻接的节点属于同一集合,则返回False
        # 我们应该遍历完所有节点,但是需要根据邻接关系先遍历一整块连在一起的节点
        # 因此维护一个队列和记录没有遍历过的节点的备忘录
        n = len(graph)
        A = set()
        B = set()
        queue = collections.deque([0])
        memo = set(range(n))
        while queue:
            i = queue.popleft()
            relation = set(graph[i])
            if i in A:
                # 自己的邻接节点与自己所处集合有交集
                if relation & A:
                    return False
                # 将自己的邻接节点放到另一个集合中
                B |= relation
            elif i in B:
                if relation & B:
                    return False
                A |= relation
            else:
                # 当某个节点不属于任何一个集合时,有两种情况
                # 1.这是第一个节点
                # 2.此节点与此前其他节点不邻接
                # 这两种情况,都是可以将这个节点随意分配到一个集合中而不影响结果的
                A.add(i)
                B |= relation
            # 将其邻接节点入队列
            for j in graph[i]:
                if j in memo:
                    queue.append(j)
                    # 即将遍历的节点从备忘录中删除
                    memo.remove(j)
            # 当队列遍历完但memo不为空时,说明还有一块节点没有遍历
            # 因此从memo中随机取一个节点加入队列
            if not queue and memo:
                queue.append(memo.pop())
        return True
posted @ 2020-07-16 11:23  luozx207  阅读(135)  评论(0编辑  收藏  举报