1
- from collections import defaultdict
2
- from queue import Queue
1
+ from collections import defaultdict , deque
3
2
4
-
5
- def check_bipartite (graph : dict [int , list [int ]]) -> bool :
3
+ def is_bipartite_dfs (graph : defaultdict [int , list [int ]]) -> bool :
6
4
"""
7
- Check if a graph is Bipartite using Depth-First Search .
5
+ Check graph bipartite using DFS .
8
6
9
7
Args:
10
- graph: Adjacency list representing the graph .
8
+ graph (defaultdict[int, list[int]]): Adjacency list .
11
9
12
10
Returns:
13
- bool: True if no edge connects same set vertices.
11
+ bool: True if bipartite, False otherwise.
12
+
13
+ Divides graph into two sets without same-set connections.
14
14
15
15
Examples:
16
- >>> is_bipartite (defaultdict(list, {0: [1, 2], 1: [0, 3], ... }))
17
- False
18
- >>> is_bipartite (defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
19
- True
16
+ >>> is_bipartite_dfs (defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4] }))
17
+ True
18
+ >>> is_bipartite_dfs (defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
19
+ False
20
20
"""
21
- queue : Queue = Queue ()
22
- visited = [False ] * len (graph )
23
- color = [- 1 ] * len (graph )
24
-
25
- def bfs () -> bool :
21
+ def dfs (node , color ):
26
22
"""
27
- Perform Breadth-First Search (BFS) on a graph to check if it's bipartite .
23
+ DFS starting from a node .
28
24
29
25
Args:
30
- graph (dict[int, list[int]]): An adjacency list representing the graph.
26
+ node: Current node.
27
+ color: Color assigned to the current node.
31
28
32
29
Returns:
33
- bool: True if there's no edge, False otherwise .
30
+ bool: True if bipartite starting from the current node .
34
31
35
32
Examples:
36
- >>> bfs({0: [1, 3], 1 : [0 , 2], 2 : [1 , 3], 3 : [0, 2]} )
37
- True
38
- >>> bfs( {0: [1, 2, 3 ], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]} )
39
- False
33
+ >>> dfs(0, 0, defaultdict(list, {0 : [1 , 2], 1 : [0 , 3], 2 : [0, 4]}) )
34
+ True
35
+ >>> dfs(0, 0, defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}) )
36
+ False
40
37
"""
41
- while not queue .empty ():
42
- u = queue .get ()
43
- visited [u ] = True
44
-
45
- for neighbour in graph [u ]:
46
- if neighbour == u :
38
+ if visited [node ] == - 1 :
39
+ visited [node ] = color
40
+ for neighbor in graph [node ]:
41
+ if not dfs (neighbor , 1 - color ):
47
42
return False
43
+ return visited [node ] == color
48
44
49
- if color [neighbour ] == - 1 :
50
- color [neighbour ] = 1 - color [u ]
51
- queue .put (neighbour )
52
-
53
- elif color [neighbour ] == color [u ]:
54
- return False
55
-
56
- return True
57
-
58
- for i in range (len (graph )):
59
- if not visited [i ]:
60
- queue .put (i )
61
- color [i ] = 0
62
- if bfs () is False :
63
- return False
64
-
45
+ visited = defaultdict (lambda : - 1 )
46
+ for node in graph :
47
+ if visited [node ] == - 1 and not dfs (node , 0 ):
48
+ return False
65
49
return True
66
50
67
-
68
- if __name__ == "__main__" :
69
- # Adjacency List of graph
70
- print (check_bipartite ({0 : [1 , 3 ], 1 : [0 , 2 ], 2 : [1 , 3 ], 3 : [0 , 2 ]}))
71
-
72
-
73
- def is_bipartite (graph : defaultdict [int , list [int ]]) -> bool :
51
+ def is_bipartite_bfs (graph : defaultdict [int , list [int ]]) -> bool :
74
52
"""
75
- Check if a graph is Bipartite using Breadth-First Search .
53
+ Check graph bipartite using BFS .
76
54
77
55
Args:
78
- graph: Adjacency list representing the graph .
56
+ graph (defaultdict[int, list[int]]): Adjacency list .
79
57
80
58
Returns:
81
- bool: True if no edge connects same set vertices.
59
+ bool: True if bipartite, False otherwise.
60
+
61
+ Divides graph into two sets without same-set connections.
82
62
83
63
Examples:
84
- >>> check_bipartite( {0: [1, 3 ], 1: [0, 2 ], 2: [1, 3], ...} )
85
- True
86
- >>> check_bipartite( {0: [1, 2, 3 ], 1: [0, 2], ...} )
87
- False
64
+ >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2 ], 1: [0, 3 ], 2: [0, 4]}) )
65
+ True
66
+ >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}) )
67
+ False
88
68
"""
69
+ visited = defaultdict (lambda : - 1 )
70
+ for node in graph :
71
+ if visited [node ] == - 1 :
72
+ queue = deque ()
73
+ queue .append (node )
74
+ visited [node ] = 0
75
+ while queue :
76
+ curr_node = queue .popleft ()
77
+ for neighbor in graph [curr_node ]:
78
+ if visited [neighbor ] == - 1 :
79
+ visited [neighbor ] = 1 - visited [curr_node ]
80
+ queue .append (neighbor )
81
+ elif visited [neighbor ] == visited [curr_node ]:
82
+ return False
83
+ return True
89
84
90
- def dfs (node : int , color : int ) -> bool :
91
- """
92
- Perform depth-first search from a node with specified color.
93
-
94
- Args:
95
- node (int): Current node being visited.
96
- color (int): Color assigned to the current node.
97
-
98
- Returns:
99
- bool: True if the graph is bipartite fromcurrent node,else False.
100
-
101
- Examples:
102
- >>> dfs(0, 0, defaultdict(list, {0: [1, 2], ...}))
103
- False
104
- >>> dfs(0, 0, defaultdict(list, {0: [1, 2], 1: [0, 2], ...}))
105
- True
106
- """
107
- visited [node ] = color
108
- return any (
109
- visited [neighbour ] == color
110
- or (visited [neighbour ] == - 1 and not dfs (neighbour , 1 - color ))
111
- for neighbour in graph [node ]
112
- )
113
-
114
- visited : defaultdict [int , int ] = defaultdict (lambda : - 1 )
115
-
116
- return all (not (visited [node ] == - 1 and not dfs (node , 0 )) for node in graph )
117
-
118
-
119
- if __name__ == "__main__" :
85
+ if __name__ == "__main" :
120
86
import doctest
121
87
122
88
result = doctest .testmod ()
@@ -125,4 +91,3 @@ def dfs(node: int, color: int) -> bool:
125
91
print (f"{ result .failed } test(s) failed." )
126
92
else :
127
93
print ("All tests passed!" )
128
-
0 commit comments