forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Concatenates both check bipatrite graphs(bfs&dfs) (TheAlgorithms#10708)
* sync * fixes#8098 * deleted: graphs/check_bipartite_graph_all.py new file: graphs/check_bipatrite,py * renamed: graphs/check_bipatrite,py -> graphs/check_bipatrite.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add the new tests --------- Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
82fc24c
commit 1976048
Showing
4 changed files
with
179 additions
and
157 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
from collections import defaultdict, deque | ||
|
||
|
||
def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool: | ||
""" | ||
Check if a graph is bipartite using depth-first search (DFS). | ||
Args: | ||
graph: Adjacency list representing the graph. | ||
Returns: | ||
True if bipartite, False otherwise. | ||
Checks if the graph can be divided into two sets of vertices, such that no two | ||
vertices within the same set are connected by an edge. | ||
Examples: | ||
# FIXME: This test should pass. | ||
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]})) | ||
Traceback (most recent call last): | ||
... | ||
RuntimeError: dictionary changed size during iteration | ||
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]})) | ||
False | ||
>>> is_bipartite_dfs({}) | ||
True | ||
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) | ||
True | ||
>>> is_bipartite_dfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]}) | ||
False | ||
>>> is_bipartite_dfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]}) | ||
True | ||
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) | ||
False | ||
>>> is_bipartite_dfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 0 | ||
# FIXME: This test should fails with KeyError: 4. | ||
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]}) | ||
False | ||
>>> is_bipartite_dfs({0: [-1, 3], 1: [0, -2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: -1 | ||
>>> is_bipartite_dfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]}) | ||
True | ||
>>> is_bipartite_dfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 0 | ||
# FIXME: This test should fails with TypeError: list indices must be integers or... | ||
>>> is_bipartite_dfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]}) | ||
True | ||
>>> is_bipartite_dfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 1 | ||
>>> is_bipartite_dfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 'b' | ||
""" | ||
|
||
def depth_first_search(node: int, color: int) -> bool: | ||
""" | ||
Perform Depth-First Search (DFS) on the graph starting from a node. | ||
Args: | ||
node: The current node being visited. | ||
color: The color assigned to the current node. | ||
Returns: | ||
True if the graph is bipartite starting from the current node, | ||
False otherwise. | ||
""" | ||
if visited[node] == -1: | ||
visited[node] = color | ||
for neighbor in graph[node]: | ||
if not depth_first_search(neighbor, 1 - color): | ||
return False | ||
return visited[node] == color | ||
|
||
visited: defaultdict[int, int] = defaultdict(lambda: -1) | ||
for node in graph: | ||
if visited[node] == -1 and not depth_first_search(node, 0): | ||
return False | ||
return True | ||
|
||
|
||
def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool: | ||
""" | ||
Check if a graph is bipartite using a breadth-first search (BFS). | ||
Args: | ||
graph: Adjacency list representing the graph. | ||
Returns: | ||
True if bipartite, False otherwise. | ||
Check if the graph can be divided into two sets of vertices, such that no two | ||
vertices within the same set are connected by an edge. | ||
Examples: | ||
# FIXME: This test should pass. | ||
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]})) | ||
Traceback (most recent call last): | ||
... | ||
RuntimeError: dictionary changed size during iteration | ||
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]})) | ||
False | ||
>>> is_bipartite_bfs({}) | ||
True | ||
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) | ||
True | ||
>>> is_bipartite_bfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]}) | ||
False | ||
>>> is_bipartite_bfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]}) | ||
True | ||
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) | ||
False | ||
>>> is_bipartite_bfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 0 | ||
# FIXME: This test should fails with KeyError: 4. | ||
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]}) | ||
False | ||
>>> is_bipartite_bfs({0: [-1, 3], 1: [0, -2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: -1 | ||
>>> is_bipartite_bfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]}) | ||
True | ||
>>> is_bipartite_bfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 0 | ||
# FIXME: This test should fails with TypeError: list indices must be integers or... | ||
>>> is_bipartite_bfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]}) | ||
True | ||
>>> is_bipartite_bfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 1 | ||
>>> is_bipartite_bfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]}) | ||
Traceback (most recent call last): | ||
... | ||
KeyError: 'b' | ||
""" | ||
visited: defaultdict[int, int] = defaultdict(lambda: -1) | ||
for node in graph: | ||
if visited[node] == -1: | ||
queue: deque[int] = deque() | ||
queue.append(node) | ||
visited[node] = 0 | ||
while queue: | ||
curr_node = queue.popleft() | ||
for neighbor in graph[curr_node]: | ||
if visited[neighbor] == -1: | ||
visited[neighbor] = 1 - visited[curr_node] | ||
queue.append(neighbor) | ||
elif visited[neighbor] == visited[curr_node]: | ||
return False | ||
return True | ||
|
||
|
||
if __name__ == "__main": | ||
import doctest | ||
|
||
result = doctest.testmod() | ||
if result.failed: | ||
print(f"{result.failed} test(s) failed.") | ||
else: | ||
print("All tests passed!") |