11from collections import defaultdict , deque
2+ from collections .abc import Iterable , Mapping
23
34
4- def is_bipartite_dfs (graph : defaultdict [int , list [int ]]) -> bool :
5+ Graph = Mapping [int , Iterable [int ]]
6+ _MISSING = object ()
7+
8+
9+ def _iter_neighbors (graph : Graph , node : int ) -> Iterable [int ]:
10+ neighbors = graph .get (node , _MISSING )
11+ if neighbors is not _MISSING :
12+ return neighbors
13+
14+ default_factory = getattr (graph , "default_factory" , None )
15+ if callable (default_factory ):
16+ return default_factory ()
17+
18+ raise KeyError (node )
19+
20+
21+ def is_bipartite_dfs (graph : Graph ) -> bool :
522 """
623 Check if a graph is bipartite using depth-first search (DFS).
724
@@ -15,11 +32,8 @@ def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
1532 vertices within the same set are connected by an edge.
1633
1734 Examples:
18- # FIXME: This test should pass.
1935 >>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
20- Traceback (most recent call last):
21- ...
22- RuntimeError: dictionary changed size during iteration
36+ True
2337 >>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]}))
2438 False
2539 >>> is_bipartite_dfs({})
@@ -78,7 +92,7 @@ def depth_first_search(node: int, color: int) -> bool:
7892 """
7993 if visited [node ] == - 1 :
8094 visited [node ] = color
81- for neighbor in graph [ node ] :
95+ for neighbor in _iter_neighbors ( graph , node ) :
8296 if not depth_first_search (neighbor , 1 - color ):
8397 return False
8498 return visited [node ] == color
@@ -90,7 +104,7 @@ def depth_first_search(node: int, color: int) -> bool:
90104 return True
91105
92106
93- def is_bipartite_bfs (graph : defaultdict [ int , list [ int ]] ) -> bool :
107+ def is_bipartite_bfs (graph : Graph ) -> bool :
94108 """
95109 Check if a graph is bipartite using a breadth-first search (BFS).
96110
@@ -104,11 +118,8 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
104118 vertices within the same set are connected by an edge.
105119
106120 Examples:
107- # FIXME: This test should pass.
108121 >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
109- Traceback (most recent call last):
110- ...
111- RuntimeError: dictionary changed size during iteration
122+ True
112123 >>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
113124 False
114125 >>> is_bipartite_bfs({})
@@ -160,7 +171,7 @@ def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
160171 visited [node ] = 0
161172 while queue :
162173 curr_node = queue .popleft ()
163- for neighbor in graph [ curr_node ] :
174+ for neighbor in _iter_neighbors ( graph , curr_node ) :
164175 if visited [neighbor ] == - 1 :
165176 visited [neighbor ] = 1 - visited [curr_node ]
166177 queue .append (neighbor )
0 commit comments