leetcode--785. Is Graph Bipartite?

问题

Given an undirected graph, return true if and only if it is bipartite.

Recall that a graph is bipartite if we can split it’s set of nodes into two independent subsets A and B such that every edge in the graph has one node in A and another node in B.

The graph is given in the following form: graph[i] is a list of indexes j for which the edge between nodes i and j exists. Each node is an integer between 0 and graph.length - 1. There are no self edges or parallel edges: graph[i] does not contain i, and it doesn’t contain any element twice.
Example 1:

Input: [[1,3], [0,2], [1,3], [0,2]]
Output: true
Explanation: 
The graph looks like this:
0----1
|    |
|    |
3----2
We can divide the vertices into two groups: {0, 2} and {1, 3}.

Example 2:

Input: [[1,2,3], [0,2], [0,1,3], [0,2]]
Output: false
Explanation: 
The graph looks like this:
0----1
| \  |
|  \ |
3----2
We cannot find a way to divide the set of nodes into two independent subsets.

Note:

  1. graph will have length in range [1, 100].
  2. graph[i] will contain integers in range [0, graph.length - 1].
  3. graph[i] will not contain i or duplicate values.
  4. The graph is undirected: if any element j is in graph[i], then i will be in graph[j].

思路与解法

题意比较简单:即判断输入的图是否可以划分为二部图。首先了解一下什么是二部图:
二部图也称作二分图,假设G=(V,E)是一个无向图,如果定点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个定点ij分别属于这两个不同的顶点集(i in A, j in B),则称图G为一个二分图。
图示如下:
在这里插入图片描述
上图中所有点分为两个集合,且每个集合中的节点之间并没有边相连。所以是一个二部图。
思路与想法如下:
对于一棵树,若可以划分为二部图,则该树的奇数深度层的节点必定位于同一集合A,同样的,所有偶数深度层的节点位于另一集合B,并且,每个集合中必定不存在有边相连的两个点。如下图所示:该树可划分为{A,D,E,F}{B,C,G,H,I,J}两个集合。
在这里插入图片描述
所以,对于图,我们也可以采用树的思想,至于如何进行集合的划分,我们可以对节点进行染色处理。从根节点开始,将根节点(深度为1)染色为Red,然后进行BFS遍历,和根节点直接相连的节点(深度为2)染色为Blue。然后与这些节点相连的节点(深度为1、2或3),便存在两种不同的情况:未染色的点和已染色的点;对于未染色的点(深度为3)我们将其染色为Red即可,但对于已染色的点,若该节点的颜色为Blue(深度为2),则说明该节点根节点相连,即深度为2的节点中存在直接相连的两个点,则该图不能划分为二部图程序终止即可;若该节点的颜色为Red,则表明该节点即为根节点(深度为1),不进行任何操作,可以继续正常遍历。在整个计算过程中,若程序没有中途退出,则表明该图可以划分为二部图。简单来说:
在染色的过程中,对于节点V(已染色),若与其相连的节点U为染色,则将U染色为异色即可;若U已染色且其颜色与V不同,则不需要进行操作;若U已染色且颜色与V相同,则提前终止程序。

代码实现

此算法我才用go语言实现:

func isBipartite(graph [][]int) bool {
	// Graph 存储图、Color存储染色状态
    Graph := make(map[int][]int)
    var Color [150]int
    for index, _ := range Color {	// 初始化Color
        Color[index] = -1
    }
    for node, edges := range graph {
        Graph[node] = edges
    }
	// 最外层循环:输入数据可能存在多个联通分量的情况,即图可能并不连通;所以需要处理每个联通分量
    for index, _ :=range Color {
    	// 以未染色的第一个节点为根节点开始BFS
        if Color[index] == -1 {
        	// 利用队列模拟BFS
            queue := make([]int, 0)
            queue = append(queue, index)
            head := 0
            // 0,1代表Red和Blue
            Color[index] = 0
            for head < len(queue) {
            	// 遍历与queue[head]相连的所有节点并进行判断
                for _, edge := range Graph[queue[head]] {
                    if Color[edge] == -1 {
                        Color[edge] = 1 - Color[queue[head]]
                        queue = append(queue, edge)
                    } else if Color[edge] == Color[queue[head]] {
                        return false
                    }
                }
                head++
            }
        }
    }
    return true
}

遇到的问题

最初代码并没有考虑图不连通的情况,所以对于多联通分量并不能通过测试:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/liuyh73/article/details/82952399
今日推荐