判断二分图
图的问题肯定要用到深度优先遍历或者广度优先遍历,但又不是单纯的深度优先遍历算法和广度优先遍历算法,而是需要在遍历的过程中加入与解决题目相关的逻辑。
题干中说了,这个图可能不是连通图,这个提示有什么作用呢?
很多时候我们接触的题目,图都是连通的,对于连通图来说,从一个点开始遍历,不管是深度优先还是广度优先,遍历一遍就可以把图中的所有点都遍历到;而对于非连通图来说,从一个点开始遍历,就无法将所有点都遍历一遍,这就需要针对每个点都进行一次遍历。
不管使用深度优先遍历算法还是使用广度优先遍历算法,都要实时记录结果,如果当前已经确定了不是连通图,那么说明结果已经确定了,就不需要继续判断,直接返回就可以。因为已经判断不是连通图,那么再继续判断下去没有意义,不是连通图的情况已经确定;如果在判断过程中,一直是连通图,那么还有没有遍历到的点,还是需要继续遍历的,因为剩下的点可能是不连通的。
1 深度优先遍历算法
class Solution {
public:enum Color {kUnColored = 0,kRed = 1,kGreen = 2};// 如果已经确定不是连通图了,就不需要继续遍历了bool isBipartite(vector<vector<int>>& graph) {int size = graph.size();// 图可能是非连通图,所以需要从每个节点开始进行一次遍历for (int i = 0; i < size && result == true; i++) {// 如果这个点没有遍历到,那么才需要遍历,已经遍历到的不需要继续遍历if (dataColor[i] == Color::kUnColored) {dfsScanGraph(graph, i, Color::kRed);}}return result;}void dfsScanGraph(vector<vector<int>> &graph, int const node, Color const color) {if (result == false) {return;}dataColor[node] = color;const Color line_color{color == Color::kRed ? Color::kGreen : Color::kRed};//给node连接的这一行的节点染色for (int data : graph[node]) {if (result == false) {return;}// 1、如果与node颜色相同,那么这两者属于同一个区域,可以确定不是二分图// 2、如果这个点还没有染色,那么进行递归染色,颜色与node不同的颜色// 3、如果节点已经染色,并且与node颜色不同,那么不做处理if (dataColor[data] == color) {result = false;return;} else if (dataColor[data] == Color::kUnColored){dfsScanGraph(graph, data, line_color); }}}private:int dataColor[101] = {0};bool result = true;
};
2 广度优先遍历算法
class Solution {
public:enum Color {kUnColored = 0,kRed = 1,kGreen = 2};bool isBipartite(vector<vector<int>>& graph) {int size = graph.size();for (int i = 0; i < size && result == true; i++) {if (dataColor[i] == Color::kUnColored) {// 广度优先遍历需要使用一个队列来辅助// 每一次广度优先遍历,都使用一个新的,空的队列std::queue<int> queue;bfsScanGraph(graph, i, Color::kRed, queue);}}return result;}void bfsScanGraph(vector<vector<int>> &graph, int const data, Color const color,std::queue<int> &queue) {if (result == false) {return;}dataColor[data] = color;queue.push(data);while (!queue.empty()) {int head_data = queue.front();queue.pop();const Color another_color{dataColor[head_data] == Color::kRed ? Color::kGreen : Color::kRed};for (int line_data : graph[head_data]) {if (result == false) {return;}if (dataColor[line_data] == Color::kUnColored) {dataColor[line_data] = another_color;queue.push(line_data);} else {// 这里比较的对象与深度优先遍历中比较的是不一样的// 深度优先比较的对象是node,广度优先比较的对象是出队的head_data// 两者的相同点,比较的对象都是与这一行的行首进行比较,行首表示这与当前这个节点是临接点if (dataColor[line_data] == dataColor[head_data]) {result = false;return;}}}}}private:int dataColor[101] = {0};bool result = true;
};