|
1 | | -from stack import Stack |
2 | 1 |
|
3 | 2 |
|
| 3 | +from typing import Dict, List, Set |
| 4 | + |
| 5 | +from stack import Stack |
| 6 | + |
4 | 7 | class Graph: |
5 | | - def __init__(self): |
6 | | - self.vertices: list = [] |
7 | | - self.adjacency_list: dict = {} |
8 | | - self.adjacency_list_reversed: dict = {} |
9 | | - self.time = 0 |
10 | | - self.visited: dict = {} |
11 | | - self.entry: dict = {} |
12 | | - self.exit: dict = {} |
| 8 | + |
| 9 | + 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]] = {} |
13 | 14 | self.stack: Stack = Stack() |
14 | | - self.connected_components: list = [] |
| 15 | + self.components: List[List[str]] = [] |
15 | 16 |
|
16 | | - def add_vertex(self, label: str): |
| 17 | + def add_vertex(self, label:str): |
17 | 18 | self.vertices.append(label) |
18 | | - self.adjacency_list[label]: list = [] |
19 | | - self.adjacency_list_reversed[label]: list = [] |
20 | | - self.visited[label] = False |
| 19 | + self.colors[label] = 'white' |
| 20 | + self.adjacency_list[label] = set() |
| 21 | + self.adjacency_list_reversed[label] = set() |
21 | 22 |
|
22 | | - def add_edge(self, label1: str, label2: str): |
23 | | - self.adjacency_list[label1].append(label2) |
24 | | - self.adjacency_list_reversed[label2].append(label1) |
| 23 | + def add_edge(self, label1:str, label2:str): |
| 24 | + self.adjacency_list[label1].add(label2) |
| 25 | + self.adjacency_list_reversed[label2].add(label1) |
25 | 26 |
|
26 | 27 | def kosaraju(self): |
27 | | - for vertex in self.vertices: |
28 | | - if not self.visited[vertex]: |
29 | | - self.dfs(vertex) |
30 | | - for vertex in self.visited: |
31 | | - self.visited[vertex] = False |
| 28 | + for label in self.vertices: |
| 29 | + if self.colors[label] == 'white': |
| 30 | + self.dfs(label) |
| 31 | + |
| 32 | + for color in self.colors: |
| 33 | + self.colors[color] = 'white' |
| 34 | + |
32 | 35 | while not self.stack.is_empty(): |
33 | | - vertex = self.stack.pop() |
34 | | - components: list = [] |
35 | | - if not self.visited[vertex]: |
36 | | - self.dfs_reversed_edges(vertex, components) |
37 | | - if len(components) > 0: |
38 | | - self.connected_components.append(components) |
39 | | - print(self.connected_components) |
40 | | - |
41 | | - def dfs(self, label: str): |
42 | | - self.visited[label] = True |
43 | | - self.time += 1 |
44 | | - self.entry[label] = self.time |
45 | | - for neighbour in self.adjacency_list[label]: |
46 | | - if not self.visited[neighbour]: |
47 | | - self.dfs(neighbour) |
48 | | - self.time += 1 |
49 | | - self.exit[label] = self.time |
| 36 | + current:str = self.stack.pop() |
| 37 | + |
| 38 | + if self.colors[current] == 'white': |
| 39 | + connected_components: List[str] = [] |
| 40 | + self.dfs_reversed(current, connected_components) |
| 41 | + |
| 42 | + self.components.append(connected_components) |
| 43 | + |
| 44 | + print(self.components) |
| 45 | + |
| 46 | + |
| 47 | + def dfs(self, label:str): |
| 48 | + self.colors[label] = 'gray' |
| 49 | + |
| 50 | + for n in self.adjacency_list[label]: |
| 51 | + if self.colors[n] == 'white': |
| 52 | + self.dfs(n) |
| 53 | + |
| 54 | + self.colors[label] = 'black' |
50 | 55 | self.stack.push(label) |
51 | 56 |
|
52 | | - def dfs_reversed_edges(self, label: str, components: list = None): |
53 | | - self.visited[label] = True |
54 | | - for neighbour in self.adjacency_list_reversed[label]: |
55 | | - if not self.visited[neighbour]: |
56 | | - self.dfs_reversed_edges(neighbour, components) |
57 | | - components.append(label) |
| 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' |
58 | 65 |
|
59 | 66 |
|
60 | 67 |
|
|
0 commit comments