Leetcode刷题笔记 758.判断二分图

758.判断二分图


时间:2020年7月16日
知识点:dfs、bfs
题目链接: https://leetcode-cn.com/problems/is-graph-bipartite/

题目
给定一个无向图graph,当这个图为二分图时返回true。

如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。

graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。

示例1
输入
[[1,3], [0,2], [1,3], [0,2]]
输出
true
说明:

无向图如下:
0----1
|    |
|    |
3----2
我们可以将节点分成两组: {0, 2}{1, 3}

示例2
输入
[[1,2,3], [0,2], [0,1,3], [0,2]]
输出
false
说明:

无向图如下:
0----1
| \  |
|  \ |
3----2
我们不能将节点分割成两个独立的子集。

注意

  1. graph 的长度范围为 [1, 100]。
  2. graph[i] 中的元素的范围为 [0, graph.length - 1]。
  3. graph[i] 不会包含 i 或者有重复的值。
  4. 图是无向的: 如果 j 在 graph[i]里边, 那么 i 也会在 graph[j]里边。

解法

  1. 对于两个有线相连的节点,不可能在同一个集合中
  2. 我们可以选择一个未染色节点,给他染红色,则和他相连的所有节点染绿色。再把那些绿色节点相连的节点染成红色,循环下去。
  3. 如果在染色的过程中,发现节点已经染色,且颜色与我们将要给它染上的颜色不相同,则不可能是个二分图。

具体操作dfs:

  1. 选择未染色节点,进入dfs
  2. dfs中的操作
    1. 给这个节点染色,定义和他相连节点的颜色(相反的颜色)
    2. 遍历和他相连的节点
    3. 如果未染色,则染相反的颜色,再进入dfs(和这个点相连的节点染色)
    4. 如果染色,且现有颜色和要染的颜色不同,则表示不是二分图

具体操作bfs:

  1. 选择未染色节点,改变颜色,创建队列,把该节点押入队列
  2. 队列不空时
    1. 取出第一个节点并弹出,定义和他相连节点的颜色(相反的颜色)
    2. 遍历和他相连的节点
    3. 如果未染色,则染相反的颜色,押入队列
    4. 如果染色,且现有颜色和要染的颜色不同,则表示不是二分图,返回

代码
DFS:

//dfs
#include <stdio.h>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <queue>
using namespace std;
 class Solution {
     int nocolor = 0;
     int red = 1; //红色为一类节点
     int green = 2; //绿色为一类节点
     vector<int> color; //定义节点颜色,区分节点
     bool res ;//是否是二分图
public:
	//返回值:void  参数:节点 颜色 图
     void dfs(int node,int c,vector<vector<int>>& graph){
        color[node] = c;//此节点染色
        int nextcolor = c==red?green:red;//定义和此节点不同的颜色
        for(int i=0;i<graph[node].size();i++)//此节点相连的节点
        {
            if(color[graph[node][i]] == 0)//未染色,进入循环
            {
                dfs(graph[node][i],nextcolor,graph);
                if(res == false)
                    return;
            }
            else if(color[graph[node][i]]!=nextcolor)//已染色,但是和我们想染的不同
            {
                res = false;
                return ;
             }
        }
     }
 
     bool isBipartite(vector<vector<int>>& graph) {
        res = true;
        color.assign(graph.size(),0);
        for(int i = 0;i<graph.size()&&res;i++)
        {
            //选择未染色的节点
            if(color[i]==0)
                dfs(i, 1, graph);
        }
        return res;
    }
 };
 int main()
{
    vector<vector<int>> ga (4,vector<int>(2));
    ga[0][0]=1; ga[0][1]=3;
    ga[1][0]=0; ga[1][1]=2;
    ga[2][0]=1; ga[2][1]=3;
    ga[3][0]=0; ga[3][1]=2;
    Solution s;
    cout<<s.isBipartite(ga);
    return 0;
}

BFS:

//bfs
#include <stdio.h>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <queue>
using namespace std;
class Solution {
    int nocolor = 0;
    int red = 1;
    int green = 2;
    vector<int> color;
public:
    bool isBipartite(vector<vector<int>>& graph) {
        bool res = true;
        int n = graph.size();
        vector<int>color(n,0);
        for(int i=0;i<n;i++)
        {
            if(color[i]==0)//未染色
            {
                color[i] = 1; //染色
                queue<int> q;
                q.push(i);
                while(!q.empty())//和他相关的所有节点,都染色
                {
                    int x = q.front();
                    q.pop();
                    int nextcolor = color[x]==red?green:red;//定义和他相连节点的颜色
                    for(int i=0;i<graph[x].size();i++)//和他相关的点
                    {
                        int tmp = graph[x][i];
                        if(color[tmp]==0)//为染色
                        {
                            color[tmp] = nextcolor;//染色
                            q.push(tmp);//押入队列,为了下次找到和他相关的节点再染色。
                        }
                        else if (color[tmp]!=nextcolor)
                        {
                            res = false;
                            return res;
                        }
                    }
                }
            }
        }
        return res;
    }
};
int main()
{
    vector<vector<int>> ga (4,vector<int>(2));
    ga[0][0]=1; ga[0][1]=3;
    ga[1][0]=0; ga[1][1]=2;
    ga[2][0]=1; ga[2][1]=3;
    ga[3][0]=0; ga[3][1]=2;
    Solution s;
    cout<<s.isBipartite(ga);
    return 0;
}

今天也是爱zz的一天哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值