|
1 |
| -# Check whether Graph is Bipartite or Not using DFS |
| 1 | +from collections import defaultdict |
2 | 2 |
|
3 | 3 |
|
4 |
| -# A Bipartite Graph is a graph whose vertices can be divided into two independent sets, |
5 |
| -# U and V such that every edge (u, v) either connects a vertex from U to V or a vertex |
6 |
| -# from V to U. In other words, for every edge (u, v), either u belongs to U and v to V, |
7 |
| -# or u belongs to V and v to U. We can also say that there is no edge that connects |
8 |
| -# vertices of same set. |
9 |
| -def check_bipartite_dfs(graph): |
10 |
| - visited = [False] * len(graph) |
11 |
| - color = [-1] * len(graph) |
| 4 | +def is_bipartite(graph: defaultdict[int, list[int]]) -> bool: |
| 5 | + """ |
| 6 | + Check whether a graph is Bipartite or not using Depth-First Search (DFS). |
12 | 7 |
|
13 |
| - def dfs(v, c): |
14 |
| - visited[v] = True |
15 |
| - color[v] = c |
16 |
| - for u in graph[v]: |
17 |
| - if not visited[u]: |
18 |
| - dfs(u, 1 - c) |
| 8 | + A Bipartite Graph is a graph whose vertices can be divided into two independent |
| 9 | + sets, U and V such that every edge (u, v) either connects a vertex from |
| 10 | + U to V or a vertex from V to U. In other words, for every edge (u, v), |
| 11 | + either u belongs to U and v to V, or u belongs to V and v to U. There is |
| 12 | + no edge that connects vertices of the same set. |
19 | 13 |
|
20 |
| - for i in range(len(graph)): |
21 |
| - if not visited[i]: |
22 |
| - dfs(i, 0) |
| 14 | + Args: |
| 15 | + graph: An adjacency list representing the graph. |
23 | 16 |
|
24 |
| - for i in range(len(graph)): |
25 |
| - for j in graph[i]: |
26 |
| - if color[i] == color[j]: |
27 |
| - return False |
| 17 | + Returns: |
| 18 | + True if there's no edge that connects vertices of the same set, False otherwise. |
28 | 19 |
|
29 |
| - return True |
| 20 | + Examples: |
| 21 | + >>> is_bipartite( |
| 22 | + ... defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4], 3: [1], 4: [2]}) |
| 23 | + ... ) |
| 24 | + False |
| 25 | + >>> is_bipartite(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]})) |
| 26 | + True |
| 27 | + """ |
30 | 28 |
|
| 29 | + def depth_first_search(node: int, color: int) -> bool: |
| 30 | + visited[node] = color |
| 31 | + return any( |
| 32 | + visited[neighbour] == color |
| 33 | + or ( |
| 34 | + visited[neighbour] == -1 |
| 35 | + and not depth_first_search(neighbour, 1 - color) |
| 36 | + ) |
| 37 | + for neighbour in graph[node] |
| 38 | + ) |
31 | 39 |
|
32 |
| -# Adjacency list of graph |
33 |
| -graph = {0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: []} |
34 |
| -print(check_bipartite_dfs(graph)) |
| 40 | + visited: defaultdict[int, int] = defaultdict(lambda: -1) |
| 41 | + |
| 42 | + return all( |
| 43 | + not (visited[node] == -1 and not depth_first_search(node, 0)) for node in graph |
| 44 | + ) |
| 45 | + |
| 46 | + |
| 47 | +if __name__ == "__main__": |
| 48 | + import doctest |
| 49 | + |
| 50 | + result = doctest.testmod() |
| 51 | + |
| 52 | + if result.failed: |
| 53 | + print(f"{result.failed} test(s) failed.") |
| 54 | + else: |
| 55 | + print("All tests passed!") |
0 commit comments