|
6 | 6 |
|
7 | 7 | class Graph:
|
8 | 8 |
|
| 9 | + |
9 | 10 | def __init__(self) -> None:
|
10 |
| - self.vertices: List[str] = [] |
11 |
| - self.colors: Dict[str, str] = {} |
12 |
| - self.adjacency_list: Dict[str, Set[str]] = {} |
13 |
| - self.adjacency_list_reversed: Dict[str, Set[str]] = {} |
14 |
| - self.stack: Stack = Stack() |
15 |
| - self.components: List[List[str]] = [] |
16 |
| - |
17 |
| - def add_vertex(self, label:str): |
18 |
| - self.vertices.append(label) |
19 |
| - self.colors[label] = 'white' |
| 11 | + self.vertices:Set[str] = set() |
| 12 | + self.adjacency_list:Dict[str, Set[str]] = dict() |
| 13 | + self.adjacency_list_reversed:Dict[str, Set[str]] = dict() |
| 14 | + self.visited:Set[str] = set() |
| 15 | + self.stack:Stack = Stack() |
| 16 | + |
| 17 | + |
| 18 | + def add_vertex(self, label:str) -> None: |
| 19 | + self.vertices.add(label) |
20 | 20 | self.adjacency_list[label] = set()
|
21 | 21 | self.adjacency_list_reversed[label] = set()
|
22 | 22 |
|
23 |
| - def add_edge(self, label1:str, label2:str): |
| 23 | + |
| 24 | + def add_edge(self, label1:str, label2:str) -> None: |
| 25 | + if label1 not in self.vertices or label2 not in self.vertices: |
| 26 | + raise Exception('Vertices are not added') |
24 | 27 | self.adjacency_list[label1].add(label2)
|
25 | 28 | self.adjacency_list_reversed[label2].add(label1)
|
26 | 29 |
|
27 |
| - def kosaraju(self): |
28 |
| - for label in self.vertices: |
29 |
| - if self.colors[label] == 'white': |
30 |
| - self.dfs(label) |
31 | 30 |
|
32 |
| - for color in self.colors: |
33 |
| - self.colors[color] = 'white' |
| 31 | + def kosaraju(self) -> List[List[str]]: |
| 32 | + for v in self.vertices: |
| 33 | + if v not in self.visited: |
| 34 | + self._dfs(v) |
| 35 | + |
| 36 | + self.visited.clear() |
| 37 | + |
| 38 | + connected_components:List[List[str]] = list() |
34 | 39 |
|
35 | 40 | while not self.stack.is_empty():
|
36 |
| - current:str = self.stack.pop() |
| 41 | + v:str = self.stack.pop() |
| 42 | + if v not in self.visited: |
| 43 | + connected:List[str] = list() |
| 44 | + self._dfs_reversed(v, connected) |
37 | 45 |
|
38 |
| - if self.colors[current] == 'white': |
39 |
| - connected_components: List[str] = [] |
40 |
| - self.dfs_reversed(current, connected_components) |
| 46 | + if len(connected) > 0: |
| 47 | + connected_components.append(connected) |
41 | 48 |
|
42 |
| - self.components.append(connected_components) |
| 49 | + return list(connected_components) |
43 | 50 |
|
44 |
| - print(self.components) |
45 | 51 |
|
46 | 52 |
|
47 |
| - def dfs(self, label:str): |
48 |
| - self.colors[label] = 'gray' |
| 53 | + def _dfs(self, label:str) -> None: |
| 54 | + self.visited.add(label) |
49 | 55 |
|
50 | 56 | for n in self.adjacency_list[label]:
|
51 |
| - if self.colors[n] == 'white': |
52 |
| - self.dfs(n) |
| 57 | + if n not in self.visited: |
| 58 | + self._dfs(n) |
53 | 59 |
|
54 |
| - self.colors[label] = 'black' |
55 | 60 | self.stack.push(label)
|
56 | 61 |
|
57 |
| - def dfs_reversed(self, label: str, connected_components:List[str]): |
58 |
| - self.colors[label] = 'gray' |
59 |
| - |
60 |
| - for n in self.adjacency_list_reversed[label]: |
61 |
| - if self.colors[n] == 'white': |
62 |
| - self.dfs_reversed(n, connected_components) |
63 |
| - connected_components.append(label) |
64 |
| - self.colors[label] = 'black' |
65 | 62 |
|
| 63 | + def _dfs_reversed(self, v:str, connected:List[str]) -> None: |
| 64 | + connected.append(v) |
| 65 | + self.visited.add(v) |
| 66 | + for n in self.adjacency_list_reversed[v]: |
| 67 | + if n not in self.visited: |
| 68 | + self._dfs_reversed(n, connected) |
66 | 69 |
|
67 | 70 |
|
68 | 71 |
|
|
0 commit comments