leetcode 785. 判断二分图(基于DFS的染色法)

leetcode 785. 判断二分图

题目来源: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. 其邻接点如果没有染色,就染上和刚才染色点不同的颜色。
  2. 其邻接点已经染色,判断其颜色与刚才染色点的颜色是否相同,如果相同,则此图必不为“二分图”,否则继续检查下一个邻接点。

直至图中的所有顶点都已经被染色,如果没有在刚才的染色过程中“判负”,则此时就可以说此图为一个“二分图”。

由于要循环所有点,就一定会涉及到“图的遍历”算法,DFS法和BFS法都可以,在这里只说一下DFS法,见代码注释,BFS法的原理类似(一个栈,一个队列的区别…)。

在这里还要说明一点注意:图中有可能出现“存在孤立点”的情况,“存在孤立点”并不会影响“二分图”的判断,因为孤立点可以染上任意一种颜色,都不会影响结果。

C++代码

class Solution {
public:
    bool isBipartite(vector<vector<int>>& graph) {
        // 使用基于DFS的染色法
        int i, j, temp, num, len;
        // 标记数组中-1为一种颜色,1为另一种颜色,0为未标记
        int mark[101] = { 0 };
        stack<int> s;
        // 获取点的个数
        num = graph.size();
        // 有可能出现“存在孤立点”的情况,
        // “存在孤立点”并不会影响“二分图”的判断,
        // 因为孤立点可以染上任意一种颜色,都不会影响结果
        for (i = 0; i < num; i++) {
            if (!mark[i]) {
                mark[i] = 1;
                s.push(i);
                while (!s.empty()) {
                    temp = s.top();
                    s.pop();
                    // 获取与该出栈点邻接的点数
                    len = graph[temp].size();
                    for (j = 0; j < len; j++) {
                        // 如果其邻接点与其分为一组则一定不是“二分图”
                        if (mark[graph[temp][j]] == mark[temp]) {
                            return false;
                        }
                        // 如果其邻接点没有被标记过,则标记它为另一组
                        else if (!mark[graph[temp][j]]) {
                            mark[graph[temp][j]] = mark[temp] * -1;
                            s.push(graph[temp][j]);
                        }
                    }
                }
            }
        }
        return true;
    }
};

发现问题欢迎指出和纠正,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值