From c2aa916c5b4b4142c3b3cc696fa5dbb16e991f88 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Fri, 21 Feb 2025 17:48:11 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.0785 (#4093) No.0785.Is Graph Bipartite --- .../0785.Is Graph Bipartite/README.md | 326 ++++++------------ .../0785.Is Graph Bipartite/README_EN.md | 247 ++++++------- .../0785.Is Graph Bipartite/Solution.cpp | 26 +- .../0785.Is Graph Bipartite/Solution.go | 16 +- .../0785.Is Graph Bipartite/Solution.java | 14 +- .../0785.Is Graph Bipartite/Solution.py | 13 +- .../0785.Is Graph Bipartite/Solution.rs | 37 +- .../0785.Is Graph Bipartite/Solution.ts | 31 +- .../0785.Is Graph Bipartite/Solution2.cpp | 33 +- .../0785.Is Graph Bipartite/Solution2.go | 11 +- .../0785.Is Graph Bipartite/Solution2.java | 12 +- .../0785.Is Graph Bipartite/Solution2.py | 11 +- .../0785.Is Graph Bipartite/Solution2.rs | 47 +-- .../0785.Is Graph Bipartite/Solution2.ts | 20 +- 14 files changed, 323 insertions(+), 521 deletions(-) diff --git a/solution/0700-0799/0785.Is Graph Bipartite/README.md b/solution/0700-0799/0785.Is Graph Bipartite/README.md index 7bb38d00e3dad..d9c3b788a3629 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/README.md +++ b/solution/0700-0799/0785.Is Graph Bipartite/README.md @@ -72,6 +72,8 @@ tags: 遍历所有节点进行染色,比如初始为白色,DFS 对节点相邻的点染上另外一种颜色。如果要染色某节点时,要染的目标颜色和该节点的已经染过的颜色不同,则说明不能构成二分图。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。 + #### Python3 @@ -79,20 +81,17 @@ tags: ```python class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def dfs(u, c): - color[u] = c - for v in graph[u]: - if not color[v]: - if not dfs(v, 3 - c): - return False - elif color[v] == c: + def dfs(a: int, c: int) -> bool: + color[a] = c + for b in graph[a]: + if color[b] == c or (color[b] == 0 and not dfs(b, -c)): return False return True n = len(graph) color = [0] * n for i in range(n): - if not color[i] and not dfs(i, 1): + if color[i] == 0 and not dfs(i, 1): return False return True ``` @@ -116,14 +115,10 @@ class Solution { return true; } - private boolean dfs(int u, int c) { - color[u] = c; - for (int v : g[u]) { - if (color[v] == 0) { - if (!dfs(v, 3 - c)) { - return false; - } - } else if (color[v] == c) { + private boolean dfs(int a, int c) { + color[a] = c; + for (int b : g[a]) { + if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) { return false; } } @@ -140,19 +135,19 @@ public: bool isBipartite(vector>& graph) { int n = graph.size(); vector color(n); - for (int i = 0; i < n; ++i) - if (!color[i] && !dfs(i, 1, color, graph)) - return false; - return true; - } - - bool dfs(int u, int c, vector& color, vector>& g) { - color[u] = c; - for (int& v : g[u]) { - if (!color[v]) { - if (!dfs(v, 3 - c, color, g)) return false; - } else if (color[v] == c) + auto dfs = [&](this auto&& dfs, int a, int c) -> bool { + color[a] = c; + for (int b : graph[a]) { + if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) { + return false; + } + } + return true; + }; + for (int i = 0; i < n; ++i) { + if (color[i] == 0 && !dfs(i, 1)) { return false; + } } return true; } @@ -165,15 +160,11 @@ public: func isBipartite(graph [][]int) bool { n := len(graph) color := make([]int, n) - var dfs func(u, c int) bool - dfs = func(u, c int) bool { - color[u] = c - for _, v := range graph[u] { - if color[v] == 0 { - if !dfs(v, 3-c) { - return false - } - } else if color[v] == c { + var dfs func(int, int) bool + dfs = func(a, c int) bool { + color[a] = c + for _, b := range graph[a] { + if color[b] == c || (color[b] == 0 && !dfs(b, -c)) { return false } } @@ -193,29 +184,22 @@ func isBipartite(graph [][]int) bool { ```ts function isBipartite(graph: number[][]): boolean { const n = graph.length; - let valid = true; - // 0 未遍历, 1 红色标记, 2 绿色标记 - let colors = new Array(n).fill(0); - function dfs(idx: number, color: number, graph: number[][]) { - colors[idx] = color; - const nextColor = 3 - color; - for (let j of graph[idx]) { - if (!colors[j]) { - dfs(j, nextColor, graph); - if (!valid) return; - } else if (colors[j] != nextColor) { - valid = false; - return; + const color: number[] = Array(n).fill(0); + const dfs = (a: number, c: number): boolean => { + color[a] = c; + for (const b of graph[a]) { + if (color[b] === c || (color[b] === 0 && !dfs(b, -c))) { + return false; } } - } - - for (let i = 0; i < n && valid; i++) { - if (!colors[i]) { - dfs(i, 1, graph); + return true; + }; + for (let i = 0; i < n; i++) { + if (color[i] === 0 && !dfs(i, 1)) { + return false; } } - return valid; + return true; } ``` @@ -223,35 +207,24 @@ function isBipartite(graph: number[][]): boolean { ```rust impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { - let mut graph = graph; let n = graph.len(); - let mut color_vec: Vec = vec![0; n]; - for i in 0..n { - if color_vec[i] == 0 && !Self::traverse(i, 1, &mut color_vec, &mut graph) { - return false; + let mut color = vec![0; n]; + + fn dfs(a: usize, c: i32, graph: &Vec>, color: &mut Vec) -> bool { + color[a] = c; + for &b in &graph[a] { + if color[b as usize] == c + || (color[b as usize] == 0 && !dfs(b as usize, -c, graph, color)) + { + return false; + } } + true } - true - } - #[allow(dead_code)] - fn traverse( - v: usize, - color: usize, - color_vec: &mut Vec, - graph: &mut Vec>, - ) -> bool { - color_vec[v] = color; - for n in graph[v].clone() { - if color_vec[n as usize] == 0 { - // This node hasn't been colored - if !Self::traverse(n as usize, 3 - color, color_vec, graph) { - return false; - } - } else if color_vec[n as usize] == color { - // The color is the same + for i in 0..n { + if color[i] == 0 && !dfs(i, 1, &graph, &mut color) { return false; } } @@ -268,70 +241,9 @@ impl Solution { ### 方法二:并查集 -对于本题,如果是二分图,那么图中每个顶点的所有邻接点都应该属于同一集合,且不与顶点处于同一集合,因此我们可以使用并查集。遍历图中每个顶点,如果发现存在当前顶点与对应的邻接点处于同一个集合,说明不是二分图。否则将当前节点的邻接点相互进行合并。以下是并查集模板。 - -模板 1——朴素并查集: - -```python -# 初始化,p存储每个点的父节点 -p = list(range(n)) - - -# 返回x的祖宗节点 -def find(x): - if p[x] != x: - # 路径压缩 - p[x] = find(p[x]) - return p[x] - - -# 合并a和b所在的两个集合 -p[find(a)] = find(b) -``` - -模板 2——维护 size 的并查集: +对于本题,如果是二分图,那么图中每个顶点的所有邻接点都应该属于同一集合,且不与顶点处于同一集合,因此我们可以使用并查集。遍历图中每个顶点,如果发现存在当前顶点与对应的邻接点处于同一个集合,说明不是二分图。否则将当前节点的邻接点相互进行合并。 -```python -# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量 -p = list(range(n)) -size = [1] * n - - -# 返回x的祖宗节点 -def find(x): - if p[x] != x: - # 路径压缩 - p[x] = find(p[x]) - return p[x] - - -# 合并a和b所在的两个集合 -if find(a) != find(b): - size[find(b)] += size[find(a)] - p[find(a)] = find(b) -``` - -模板 3——维护到祖宗节点距离的并查集: - -```python -# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离 -p = list(range(n)) -d = [0] * n - - -# 返回x的祖宗节点 -def find(x): - if p[x] != x: - t = find(p[x]) - d[x] += d[p[x]] - p[x] = t - return p[x] - - -# 合并a和b所在的两个集合 -p[find(a)] = find(b) -d[find(a)] = distance -``` +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为节点数。 @@ -340,17 +252,18 @@ d[find(a)] = distance ```python class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] p = list(range(len(graph))) - for u, g in enumerate(graph): - for v in g: - if find(u) == find(v): + for a, bs in enumerate(graph): + for b in bs: + pa, pb = find(a), find(b) + if pa == pb: return False - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) return True ``` @@ -366,13 +279,13 @@ class Solution { for (int i = 0; i < n; ++i) { p[i] = i; } - for (int u = 0; u < n; ++u) { - int[] g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) { + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { return false; } - p[find(v)] = find(g[0]); + p[pb] = find(graph[a][0]); } } return true; @@ -392,25 +305,26 @@ class Solution { ```cpp class Solution { public: - vector p; - bool isBipartite(vector>& graph) { int n = graph.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int u = 0; u < n; ++u) { - auto& g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) return 0; - p[find(v)] = find(g[0]); + vector p(n); + iota(p.begin(), p.end(), 0); + auto find = [&](this auto&& find, int x) -> int { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + p[pb] = find(graph[a][0]); } } - return 1; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; + return true; } }; ``` @@ -431,12 +345,13 @@ func isBipartite(graph [][]int) bool { } return p[x] } - for u, g := range graph { - for _, v := range g { - if find(u) == find(v) { + for a, bs := range graph { + for _, b := range bs { + pa, pb := find(a), find(b) + if pa == pb { return false } - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) } } return true @@ -448,22 +363,20 @@ func isBipartite(graph [][]int) bool { ```ts function isBipartite(graph: number[][]): boolean { const n = graph.length; - let p = new Array(n); - for (let i = 0; i < n; ++i) { - p[i] = i; - } - function find(x) { - if (p[x] != x) { + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (x !== p[x]) { p[x] = find(p[x]); } return p[x]; - } - for (let u = 0; u < n; ++u) { - for (let v of graph[u]) { - if (find(u) == find(v)) { + }; + for (let a = 0; a < n; ++a) { + for (const b of graph[a]) { + const [pa, pb] = [find(a), find(b)]; + if (pa === pb) { return false; } - p[find(v)] = find(graph[u][0]); + p[pb] = find(graph[a][0]); } } return true; @@ -474,50 +387,29 @@ function isBipartite(graph: number[][]): boolean { ```rust impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { let n = graph.len(); - let mut disjoint_set: Vec = vec![0; n]; - // Initialize the disjoint set - for i in 0..n { - disjoint_set[i] = i; - } + let mut p: Vec = (0..n).collect(); - // Traverse the graph - for i in 0..n { - if graph[i].is_empty() { - continue; + fn find(x: usize, p: &mut Vec) -> usize { + if p[x] != x { + p[x] = find(p[x], p); } - let first = graph[i][0] as usize; - for v in &graph[i] { - let v = *v as usize; - let i_p = Self::find(i, &mut disjoint_set); - let v_p = Self::find(v, &mut disjoint_set); - if i_p == v_p { + p[x] + } + + for a in 0..n { + for &b in &graph[a] { + let pa = find(a, &mut p); + let pb = find(b as usize, &mut p); + if pa == pb { return false; } - // Otherwise, union the node - Self::union(first, v, &mut disjoint_set); + p[pb] = find(graph[a][0] as usize, &mut p); } } - true } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } } ``` diff --git a/solution/0700-0799/0785.Is Graph Bipartite/README_EN.md b/solution/0700-0799/0785.Is Graph Bipartite/README_EN.md index b748279581ce6..e89a422fe697e 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/README_EN.md +++ b/solution/0700-0799/0785.Is Graph Bipartite/README_EN.md @@ -66,7 +66,11 @@ tags: -### Solution 1 +### Solution 1: Coloring Method to Determine Bipartite Graph + +Traverse all nodes for coloring. For example, initially color them white, and use DFS to color the adjacent nodes with another color. If the target color to be colored is different from the color that the node has already been colored, it means that it cannot form a bipartite graph. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes. @@ -75,20 +79,17 @@ tags: ```python class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def dfs(u, c): - color[u] = c - for v in graph[u]: - if not color[v]: - if not dfs(v, 3 - c): - return False - elif color[v] == c: + def dfs(a: int, c: int) -> bool: + color[a] = c + for b in graph[a]: + if color[b] == c or (color[b] == 0 and not dfs(b, -c)): return False return True n = len(graph) color = [0] * n for i in range(n): - if not color[i] and not dfs(i, 1): + if color[i] == 0 and not dfs(i, 1): return False return True ``` @@ -112,14 +113,10 @@ class Solution { return true; } - private boolean dfs(int u, int c) { - color[u] = c; - for (int v : g[u]) { - if (color[v] == 0) { - if (!dfs(v, 3 - c)) { - return false; - } - } else if (color[v] == c) { + private boolean dfs(int a, int c) { + color[a] = c; + for (int b : g[a]) { + if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) { return false; } } @@ -161,15 +158,11 @@ public: func isBipartite(graph [][]int) bool { n := len(graph) color := make([]int, n) - var dfs func(u, c int) bool - dfs = func(u, c int) bool { - color[u] = c - for _, v := range graph[u] { - if color[v] == 0 { - if !dfs(v, 3-c) { - return false - } - } else if color[v] == c { + var dfs func(int, int) bool + dfs = func(a, c int) bool { + color[a] = c + for _, b := range graph[a] { + if color[b] == c || (color[b] == 0 && !dfs(b, -c)) { return false } } @@ -189,29 +182,22 @@ func isBipartite(graph [][]int) bool { ```ts function isBipartite(graph: number[][]): boolean { const n = graph.length; - let valid = true; - // 0 未遍历, 1 红色标记, 2 绿色标记 - let colors = new Array(n).fill(0); - function dfs(idx: number, color: number, graph: number[][]) { - colors[idx] = color; - const nextColor = 3 - color; - for (let j of graph[idx]) { - if (!colors[j]) { - dfs(j, nextColor, graph); - if (!valid) return; - } else if (colors[j] != nextColor) { - valid = false; - return; + const color: number[] = Array(n).fill(0); + const dfs = (a: number, c: number): boolean => { + color[a] = c; + for (const b of graph[a]) { + if (color[b] === c || (color[b] === 0 && !dfs(b, -c))) { + return false; } } - } - - for (let i = 0; i < n && valid; i++) { - if (!colors[i]) { - dfs(i, 1, graph); + return true; + }; + for (let i = 0; i < n; i++) { + if (color[i] === 0 && !dfs(i, 1)) { + return false; } } - return valid; + return true; } ``` @@ -219,35 +205,24 @@ function isBipartite(graph: number[][]): boolean { ```rust impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { - let mut graph = graph; let n = graph.len(); - let mut color_vec: Vec = vec![0; n]; - for i in 0..n { - if color_vec[i] == 0 && !Self::traverse(i, 1, &mut color_vec, &mut graph) { - return false; + let mut color = vec![0; n]; + + fn dfs(a: usize, c: i32, graph: &Vec>, color: &mut Vec) -> bool { + color[a] = c; + for &b in &graph[a] { + if color[b as usize] == c + || (color[b as usize] == 0 && !dfs(b as usize, -c, graph, color)) + { + return false; + } } + true } - true - } - #[allow(dead_code)] - fn traverse( - v: usize, - color: usize, - color_vec: &mut Vec, - graph: &mut Vec>, - ) -> bool { - color_vec[v] = color; - for n in graph[v].clone() { - if color_vec[n as usize] == 0 { - // This node hasn't been colored - if !Self::traverse(n as usize, 3 - color, color_vec, graph) { - return false; - } - } else if color_vec[n as usize] == color { - // The color is the same + for i in 0..n { + if color[i] == 0 && !dfs(i, 1, &graph, &mut color) { return false; } } @@ -262,7 +237,11 @@ impl Solution { -### Solution 2 +### Solution 2: Union-Find + +For this problem, if it is a bipartite graph, then all adjacent nodes of each vertex in the graph should belong to the same set and not be in the same set as the vertex. Therefore, we can use the union-find method. Traverse each vertex in the graph, and if it is found that the current vertex and its corresponding adjacent nodes are in the same set, it means that it is not a bipartite graph. Otherwise, merge the adjacent nodes of the current node. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes. @@ -271,17 +250,18 @@ impl Solution { ```python class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] p = list(range(len(graph))) - for u, g in enumerate(graph): - for v in g: - if find(u) == find(v): + for a, bs in enumerate(graph): + for b in bs: + pa, pb = find(a), find(b) + if pa == pb: return False - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) return True ``` @@ -297,13 +277,13 @@ class Solution { for (int i = 0; i < n; ++i) { p[i] = i; } - for (int u = 0; u < n; ++u) { - int[] g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) { + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { return false; } - p[find(v)] = find(g[0]); + p[pb] = find(graph[a][0]); } } return true; @@ -323,25 +303,26 @@ class Solution { ```cpp class Solution { public: - vector p; - bool isBipartite(vector>& graph) { int n = graph.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int u = 0; u < n; ++u) { - auto& g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) return 0; - p[find(v)] = find(g[0]); + vector p(n); + iota(p.begin(), p.end(), 0); + auto find = [&](this auto&& find, int x) -> int { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + p[pb] = find(graph[a][0]); } } - return 1; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; + return true; } }; ``` @@ -362,12 +343,13 @@ func isBipartite(graph [][]int) bool { } return p[x] } - for u, g := range graph { - for _, v := range g { - if find(u) == find(v) { + for a, bs := range graph { + for _, b := range bs { + pa, pb := find(a), find(b) + if pa == pb { return false } - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) } } return true @@ -379,22 +361,20 @@ func isBipartite(graph [][]int) bool { ```ts function isBipartite(graph: number[][]): boolean { const n = graph.length; - let p = new Array(n); - for (let i = 0; i < n; ++i) { - p[i] = i; - } - function find(x) { - if (p[x] != x) { + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (x !== p[x]) { p[x] = find(p[x]); } return p[x]; - } - for (let u = 0; u < n; ++u) { - for (let v of graph[u]) { - if (find(u) == find(v)) { + }; + for (let a = 0; a < n; ++a) { + for (const b of graph[a]) { + const [pa, pb] = [find(a), find(b)]; + if (pa === pb) { return false; } - p[find(v)] = find(graph[u][0]); + p[pb] = find(graph[a][0]); } } return true; @@ -405,50 +385,29 @@ function isBipartite(graph: number[][]): boolean { ```rust impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { let n = graph.len(); - let mut disjoint_set: Vec = vec![0; n]; - // Initialize the disjoint set - for i in 0..n { - disjoint_set[i] = i; - } + let mut p: Vec = (0..n).collect(); - // Traverse the graph - for i in 0..n { - if graph[i].is_empty() { - continue; + fn find(x: usize, p: &mut Vec) -> usize { + if p[x] != x { + p[x] = find(p[x], p); } - let first = graph[i][0] as usize; - for v in &graph[i] { - let v = *v as usize; - let i_p = Self::find(i, &mut disjoint_set); - let v_p = Self::find(v, &mut disjoint_set); - if i_p == v_p { + p[x] + } + + for a in 0..n { + for &b in &graph[a] { + let pa = find(a, &mut p); + let pb = find(b as usize, &mut p); + if pa == pb { return false; } - // Otherwise, union the node - Self::union(first, v, &mut disjoint_set); + p[pb] = find(graph[a][0] as usize, &mut p); } } - true } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } } ``` diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.cpp b/solution/0700-0799/0785.Is Graph Bipartite/Solution.cpp index a70e6639c8023..565c0eaa71bad 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.cpp +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.cpp @@ -3,20 +3,20 @@ class Solution { bool isBipartite(vector>& graph) { int n = graph.size(); vector color(n); - for (int i = 0; i < n; ++i) - if (!color[i] && !dfs(i, 1, color, graph)) - return false; - return true; - } - - bool dfs(int u, int c, vector& color, vector>& g) { - color[u] = c; - for (int& v : g[u]) { - if (!color[v]) { - if (!dfs(v, 3 - c, color, g)) return false; - } else if (color[v] == c) + auto dfs = [&](this auto&& dfs, int a, int c) -> bool { + color[a] = c; + for (int b : graph[a]) { + if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) { + return false; + } + } + return true; + }; + for (int i = 0; i < n; ++i) { + if (color[i] == 0 && !dfs(i, 1)) { return false; + } } return true; } -}; \ No newline at end of file +}; diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.go b/solution/0700-0799/0785.Is Graph Bipartite/Solution.go index a1188489cd5b6..6074b49b7ff8f 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.go +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.go @@ -1,15 +1,11 @@ func isBipartite(graph [][]int) bool { n := len(graph) color := make([]int, n) - var dfs func(u, c int) bool - dfs = func(u, c int) bool { - color[u] = c - for _, v := range graph[u] { - if color[v] == 0 { - if !dfs(v, 3-c) { - return false - } - } else if color[v] == c { + var dfs func(int, int) bool + dfs = func(a, c int) bool { + color[a] = c + for _, b := range graph[a] { + if color[b] == c || (color[b] == 0 && !dfs(b, -c)) { return false } } @@ -21,4 +17,4 @@ func isBipartite(graph [][]int) bool { } } return true -} \ No newline at end of file +} diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.java b/solution/0700-0799/0785.Is Graph Bipartite/Solution.java index 7b86d27d7c235..4496ebf871fcc 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.java +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.java @@ -14,17 +14,13 @@ public boolean isBipartite(int[][] graph) { return true; } - private boolean dfs(int u, int c) { - color[u] = c; - for (int v : g[u]) { - if (color[v] == 0) { - if (!dfs(v, 3 - c)) { - return false; - } - } else if (color[v] == c) { + private boolean dfs(int a, int c) { + color[a] = c; + for (int b : g[a]) { + if (color[b] == c || (color[b] == 0 && !dfs(b, -c))) { return false; } } return true; } -} \ No newline at end of file +} diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.py b/solution/0700-0799/0785.Is Graph Bipartite/Solution.py index 1d41a8d535898..737f649975bff 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.py +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.py @@ -1,18 +1,15 @@ class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def dfs(u, c): - color[u] = c - for v in graph[u]: - if not color[v]: - if not dfs(v, 3 - c): - return False - elif color[v] == c: + def dfs(a: int, c: int) -> bool: + color[a] = c + for b in graph[a]: + if color[b] == c or (color[b] == 0 and not dfs(b, -c)): return False return True n = len(graph) color = [0] * n for i in range(n): - if not color[i] and not dfs(i, 1): + if color[i] == 0 and not dfs(i, 1): return False return True diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.rs b/solution/0700-0799/0785.Is Graph Bipartite/Solution.rs index 29bb619a8d7ed..0099451d81b7c 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.rs +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.rs @@ -1,33 +1,22 @@ impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { - let mut graph = graph; let n = graph.len(); - let mut color_vec: Vec = vec![0; n]; - for i in 0..n { - if color_vec[i] == 0 && !Self::traverse(i, 1, &mut color_vec, &mut graph) { - return false; - } - } - true - } + let mut color = vec![0; n]; - #[allow(dead_code)] - fn traverse( - v: usize, - color: usize, - color_vec: &mut Vec, - graph: &mut Vec>, - ) -> bool { - color_vec[v] = color; - for n in graph[v].clone() { - if color_vec[n as usize] == 0 { - // This node hasn't been colored - if !Self::traverse(n as usize, 3 - color, color_vec, graph) { + fn dfs(a: usize, c: i32, graph: &Vec>, color: &mut Vec) -> bool { + color[a] = c; + for &b in &graph[a] { + if color[b as usize] == c + || (color[b as usize] == 0 && !dfs(b as usize, -c, graph, color)) + { return false; } - } else if color_vec[n as usize] == color { - // The color is the same + } + true + } + + for i in 0..n { + if color[i] == 0 && !dfs(i, 1, &graph, &mut color) { return false; } } diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution.ts b/solution/0700-0799/0785.Is Graph Bipartite/Solution.ts index 88692c15ebc97..a49cb76c826b1 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution.ts +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution.ts @@ -1,26 +1,19 @@ function isBipartite(graph: number[][]): boolean { const n = graph.length; - let valid = true; - // 0 未遍历, 1 红色标记, 2 绿色标记 - let colors = new Array(n).fill(0); - function dfs(idx: number, color: number, graph: number[][]) { - colors[idx] = color; - const nextColor = 3 - color; - for (let j of graph[idx]) { - if (!colors[j]) { - dfs(j, nextColor, graph); - if (!valid) return; - } else if (colors[j] != nextColor) { - valid = false; - return; + const color: number[] = Array(n).fill(0); + const dfs = (a: number, c: number): boolean => { + color[a] = c; + for (const b of graph[a]) { + if (color[b] === c || (color[b] === 0 && !dfs(b, -c))) { + return false; } } - } - - for (let i = 0; i < n && valid; i++) { - if (!colors[i]) { - dfs(i, 1, graph); + return true; + }; + for (let i = 0; i < n; i++) { + if (color[i] === 0 && !dfs(i, 1)) { + return false; } } - return valid; + return true; } diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.cpp b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.cpp index 73ab8a67cc3a2..9b6721564f42f 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.cpp +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.cpp @@ -1,23 +1,24 @@ class Solution { public: - vector p; - bool isBipartite(vector>& graph) { int n = graph.size(); - p.resize(n); - for (int i = 0; i < n; ++i) p[i] = i; - for (int u = 0; u < n; ++u) { - auto& g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) return 0; - p[find(v)] = find(g[0]); + vector p(n); + iota(p.begin(), p.end(), 0); + auto find = [&](this auto&& find, int x) -> int { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + }; + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { + return false; + } + p[pb] = find(graph[a][0]); } } - return 1; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; + return true; } -}; \ No newline at end of file +}; diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.go b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.go index f52ba18b0283d..f1302dc7603a4 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.go +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.go @@ -11,13 +11,14 @@ func isBipartite(graph [][]int) bool { } return p[x] } - for u, g := range graph { - for _, v := range g { - if find(u) == find(v) { + for a, bs := range graph { + for _, b := range bs { + pa, pb := find(a), find(b) + if pa == pb { return false } - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) } } return true -} \ No newline at end of file +} diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.java b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.java index f40f2a480dbf7..e2805f0d80407 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.java +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.java @@ -7,13 +7,13 @@ public boolean isBipartite(int[][] graph) { for (int i = 0; i < n; ++i) { p[i] = i; } - for (int u = 0; u < n; ++u) { - int[] g = graph[u]; - for (int v : g) { - if (find(u) == find(v)) { + for (int a = 0; a < n; ++a) { + for (int b : graph[a]) { + int pa = find(a), pb = find(b); + if (pa == pb) { return false; } - p[find(v)] = find(g[0]); + p[pb] = find(graph[a][0]); } } return true; @@ -25,4 +25,4 @@ private int find(int x) { } return p[x]; } -} \ No newline at end of file +} diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.py b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.py index 32761a802ef55..dad6523867e78 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.py +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.py @@ -1,14 +1,15 @@ class Solution: def isBipartite(self, graph: List[List[int]]) -> bool: - def find(x): + def find(x: int) -> int: if p[x] != x: p[x] = find(p[x]) return p[x] p = list(range(len(graph))) - for u, g in enumerate(graph): - for v in g: - if find(u) == find(v): + for a, bs in enumerate(graph): + for b in bs: + pa, pb = find(a), find(b) + if pa == pb: return False - p[find(v)] = find(g[0]) + p[pb] = find(bs[0]) return True diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.rs b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.rs index 574f7c1e9d66c..c8ba064cf989f 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.rs +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.rs @@ -1,46 +1,25 @@ impl Solution { - #[allow(dead_code)] pub fn is_bipartite(graph: Vec>) -> bool { let n = graph.len(); - let mut disjoint_set: Vec = vec![0; n]; - // Initialize the disjoint set - for i in 0..n { - disjoint_set[i] = i; - } + let mut p: Vec = (0..n).collect(); - // Traverse the graph - for i in 0..n { - if graph[i].is_empty() { - continue; + fn find(x: usize, p: &mut Vec) -> usize { + if p[x] != x { + p[x] = find(p[x], p); } - let first = graph[i][0] as usize; - for v in &graph[i] { - let v = *v as usize; - let i_p = Self::find(i, &mut disjoint_set); - let v_p = Self::find(v, &mut disjoint_set); - if i_p == v_p { + p[x] + } + + for a in 0..n { + for &b in &graph[a] { + let pa = find(a, &mut p); + let pb = find(b as usize, &mut p); + if pa == pb { return false; } - // Otherwise, union the node - Self::union(first, v, &mut disjoint_set); + p[pb] = find(graph[a][0] as usize, &mut p); } } - true } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } } diff --git a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.ts b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.ts index 76b038b2ffe62..d73f02682b879 100644 --- a/solution/0700-0799/0785.Is Graph Bipartite/Solution2.ts +++ b/solution/0700-0799/0785.Is Graph Bipartite/Solution2.ts @@ -1,21 +1,19 @@ function isBipartite(graph: number[][]): boolean { const n = graph.length; - let p = new Array(n); - for (let i = 0; i < n; ++i) { - p[i] = i; - } - function find(x) { - if (p[x] != x) { + const p: number[] = Array.from({ length: n }, (_, i) => i); + const find = (x: number): number => { + if (x !== p[x]) { p[x] = find(p[x]); } return p[x]; - } - for (let u = 0; u < n; ++u) { - for (let v of graph[u]) { - if (find(u) == find(v)) { + }; + for (let a = 0; a < n; ++a) { + for (const b of graph[a]) { + const [pa, pb] = [find(a), find(b)]; + if (pa === pb) { return false; } - p[find(v)] = find(graph[u][0]); + p[pb] = find(graph[a][0]); } } return true;