二分图

二分图定义:

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。简而言之,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。

785. 判断二分图

题目
对于图中的任意两个节点 u 和 v,如果它们之间有一条边直接相连,那么 u 和 v 必须属于不同的集合。

如果给定的无向图连通,那么我们就可以任选一个节点开始,给它染成红色。随后我们对整个图进行遍历,将该节点直接相连的所有节点染成绿色,表示这些节点不能与起始节点属于同一个集合。我们再将这些绿色节点直接相连的所有节点染成红色,以此类推,直到无向图中的每个节点均被染色。

如果我们能够成功染色,那么红色和绿色的节点各属于一个集合,这个无向图就是一个二分图;如果我们未能成功染色,即在染色的过程中,某一时刻访问到了一个已经染色的节点,并且它的颜色与我们将要给它染上的颜色不相同,也就说明这个无向图不是一个二分图。

算法的流程如下:

  • 我们任选一个节点开始,将其染成红色,并从该节点开始对整个无向图进行遍历;
  • 在遍历的过程中,如果我们通过节点 u 遍历到了节点 v(即 uu 和 vv 在图中有一条边直接相连),那么会有两种情况:
    如果 v 未被染色,那么我们将其染成与 u不同的颜色,并对 v 直接相连的节点进行遍历;
    如果 v 被染色,并且颜色与 u 相同,那么说明给定的无向图不是二分图。我们可以直接退出遍历并返回False 作为答案。
  • 当遍历结束时,说明给定的无向图是二分图,返回 True 作为答案。

可以使用「深度优先搜索」或「广度优先搜索」对无向图进行遍历,下文分别给出了这两种搜索对应的代码。

注意:题目中给定的无向图不一定保证连通,因此我们需要进行多次遍历,直到每一个节点都被染色,或确定答案为False 为止。每次遍历开始时,我们任选一个未被染色的节点,将所有与该节点直接或间接相连的节点进行染色。

方法一: DFS
class Solution {
private:
    bool valid;
    vector<int> color;
    int UNCOLORED=0;
    int RED=1;
    int GREEN=2;
public:
    bool isBipartite(vector<vector<int>>& graph) {
        int n=graph.size();
        valid=true;
        color.assign(n,UNCOLORED);
        for(int i=0;i<n&&valid;i++){
            if(color[i]==UNCOLORED){
                dfs(i,RED,graph);
            }
        }
        return valid;
    }
    void dfs(int x,int COLOR,vector<vector<int>> &graph){
        color[x]=COLOR;
        int cNei=(COLOR==RED?GREEN:RED);
        for(int nei:graph[x]){
            if(color[nei]==UNCOLORED) {
                dfs(nei,cNei,graph);
                if(!valid){
                    return;
                }
            }else if(color[nei]!=cNei){
                valid=false;
                return;
            }
        }
    }
};
方法二:BFS
class Solution {
private:
    vector<int> color;
    int UNCOLORED=0;
    int RED=1;
    int GREEN=2;
public:
    bool isBipartite(vector<vector<int>>& graph) {
        int n=graph.size();
        color.assign(n,UNCOLORED);
        for(int i=0;i<n;i++){
            if(color[i]==UNCOLORED){
                queue<int> qn;                
                qn.push(i);
                color[i]=RED;
                while(!qn.empty()){
                    int k=qn.front();qn.pop();
                    int cNei=(color[k]==RED?GREEN:RED);
                    for(int nei:graph[k]){
                        if(color[nei]==UNCOLORED){
                            qn.push(nei);
                            color[nei]=cNei;
                        }else if(color[nei]!=cNei){
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }
};

你可能感兴趣的:(leetcode,#,图)