|
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