Week4

Week4(2)

上周犯了个小错误,在写第3周的博客时,不小心直接在第2周的博客上改了,然后第2周的博客直接被第3周的覆盖了,所以这周写2篇补回来。
Graph
question source: Is Graph Bipartite?

question description

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:

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

这周学习了图的分解,选这道题是因为老师上课讲课后习题的时候讲了类似的题的算法,刚好就看到有,就实现了。在中文教材的111页,3.7题,二部图是这样的图,其顶点可以划分为两人子集,并且子集内部的顶点之间没有边相连。这条性质可以有多种表述方式,例如,无向图是二部图,当且仅当用两种颜色就可以为它着色无向图是二部图当且仅当它不包含长度为奇数的环。 这几种表示都是可以的,用颜色好理解一点。遍历这个图,用两种颜色来标记点,如果相临的两个点颜色相同,则不是二部图。

解决方法

做法1,使用BFS,每一层的颜色都和上一层的颜色不同,上色之后检查顶点有没有指向相同颜色的顶点。具体实现方法是,用一个color的数组,为0时表示还没被染色,也就是说没有被访问过,用1和-1来区别不同的颜色,这样对下一层的点染色时,只要将这一层的颜色取反就行了。

实现代码如下

class Solution {
public:
        bool isBipartite(vector<vector<int>>& graph) {
        //bfs
        int size = graph.size();
        int n = 0;
        queue<int> q;
        int color[size];
        memset(color, 0, sizeof(color));
        q.push(0);
        color[0] = 1;
        while(n != size){
            int v = q.front();
            n++;
            for(int i = 0; i < graph[v].size(); i++){
                if(color[graph[v][i]] == color[v]){
                    return false;
                }else if(color[graph[v][i]] == 0){
                    color[graph[v][i]] = (-1) * color[v];
                    q.push(graph[v][i]);
                }
            
     }
            q.pop();
            // The graph is not connected
            if(q.size() == 0 && n != size){
                for(int i = 0; i < size; i++){
                    if(color[i] == 0){
                        q.push(i);
                        color[i] = 1;
                        break;
                    }
                }  
            }
            
        }
        return true;
    }
};

第2种方法,做法1,使用DFS,每个点的相临点都染上不同的颜色,同时对正在染色的点进行检查,如果发现相临的点有相同颜色,则不是二部图。DFS用递归实现。

实现代码如下

class Solution {
public:
    bool isBipartite(vector<vector<int>>& graph) {
        //dfs
        int size = graph.size();
        int color[size];
        memset(color, 0, sizeof(color));
        int n = 0;
        int v = 0;
        bool flag = true;
        while(true){
            color[v] = 1;
            visit(v, graph, n, color, flag);
            if(!flag){
                return false;
            }
            if(n == size){
                return true;
            }
            for(int i = 0; i < graph.size(); i++){
                if(color[i] == 0){
                    v = i;
                    break;
                }
            }        
        }      
    }
    void visit(int v, vector<vector<int>> & graph, int& n, int* color, bool& flag){
        if(!flag){
            return;
        }
        n++;
        for(int i = 0; i < graph[v].size(); i++){
            if(color[graph[v][i]] == color[v]){
                flag = false;
                return;
            }else if(color[graph[v][i]] == 0){
                color[graph[v][i]] = -1 * color[v];
                visit(graph[v][i], graph, n, color, flag);
            }
        }     
    }
};

思路是很清晰的,但实现起来就有各种问题。一开始时用一个数组来表示是否访问过,用另一个数组来记录颜色。这样实现起来即不方便,而且也没必要。后来觉得用一个数组就能实现这个功能了。

猜你喜欢

转载自blog.csdn.net/pjsfirstlaw/article/details/82903722
今日推荐