LeetCode785 判断二分图
题目
存在一个无向图,图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph ,其中 graph[u] 是一个节点数组,由节点 u 的邻接节点组成。形式上,对于 graph[u] 中的每个 v ,都存在一条位于节点 u 和节点 v 之间的无向边。该无向图同时具有以下属性:
- 不存在自环(graph[u] 不包含 u)。
- 不存在平行边(graph[u] 不包含重复值)。
- 如果 v 在 graph[u] 内,那么 u 也应该在 graph[v] 内(该图是无向图)
- 这个图可能不是连通图,也就是说两个节点 u 和 v 之间可能不存在一条连通彼此的路径。
二分图定义:如果能将一个图的节点集合分割成两个独立的子集 A 和 B ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。
如果图是二分图,返回 true ;否则,返回 false 。
示例 1:不是一个二分图
示例二:是一个二分图
解题思路
这是一道判断是否是二分图的题目,类似于图着色,可以抽象成能不能将图中的每条边的两个节点涂上不同的颜色。关于二分图的知识可以看我的另一篇博客图结构专栏——判断二分图。这道题可以用dfs和bfs两种方法解决。
2.1 深度优先遍历
vector<int> visited;
bool ok = true;
void dfs(vector<vector<int>>& graph, int thisnode, int lastnode)
{
if (lastnode == -1)
{
}
else
{
if (visited[thisnode] == -1)//这个节点还未访问
{
visited[thisnode] = visited[lastnode] ^ 1;
}
else//这个节点访问过
{
if (visited[thisnode] ^ 1 != visited[lastnode])
{
ok = false;
}
return;
}
}
for (int i = 0; i < graph[thisnode].size(); i++)
{
dfs(graph, graph[thisnode][i], thisnode);
}
}
//参数graph:graph[i]是一个容器,装有与节点i相连的节点
bool isBipartite(vector<vector<int>>& graph) {
visited.resize(graph.size(), -1);
for (int i = 0; i < graph.size(); i++)
{
if (visited[i] == -1)
{
visited[i] = 0;
dfs(graph, i, -1);
}
}
return ok;
}
2.2广度优先遍历
class Solution {
public:
vector<int> visited;
bool isBipartite(vector<vector<int>>& graph) {
visited.resize(graph.size(), -1);
queue<int> q;
for (int i = 0; i < graph.size(); i++)
{
if (visited[i] == -1)
{
visited[i] = 0;
q.push(i);
while (!q.empty())
{
int thisnode = q.front();
q.pop();
for (int j = 0; j < graph[thisnode].size(); j++)
{
if (visited[graph[thisnode][j]] != -1)
{
if (visited[graph[thisnode][j]] == visited[thisnode])
return false;
}
else
{
visited[graph[thisnode][j]] = visited[thisnode] ^ 1;
q.push(graph[thisnode][j]);
}
}
}
}
}
return true;
}
};