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]中没有重复的值。
思路
判断无向图是否为“二分图”的一个常用方法为“染色法”。
对图中的任一点进行染色,并找出该点的邻接点:
- 其邻接点如果没有染色,就染上和刚才染色点不同的颜色。
- 其邻接点已经染色,判断其颜色与刚才染色点的颜色是否相同,如果相同,则此图必不为“二分图”,否则继续检查下一个邻接点。
直至图中的所有顶点都已经被染色,如果没有在刚才的染色过程中“判负”,则此时就可以说此图为一个“二分图”。
由于要循环所有点,就一定会涉及到“图的遍历”算法,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;
}
};
发现问题欢迎指出和纠正,谢谢!