-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Expand file tree
/
Copy pathpath_between_two_vertices_in_digraph.py
More file actions
81 lines (63 loc) · 2.12 KB
/
path_between_two_vertices_in_digraph.py
File metadata and controls
81 lines (63 loc) · 2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""
Path Between Two Vertices in a Directed Graph
Determines whether there is a directed path from a source vertex to a
target vertex using DFS.
Complexity:
Time: O(V + E)
Space: O(V)
"""
from __future__ import annotations
from collections import defaultdict
class Graph:
"""A directed graph for reachability queries."""
def __init__(self, vertex_count: int) -> None:
"""Create a graph with *vertex_count* vertices.
Args:
vertex_count: Number of vertices.
"""
self.vertex_count = vertex_count
self.graph: dict[int, list[int]] = defaultdict(list)
self.has_path = False
def add_edge(self, source: int, target: int) -> None:
"""Add a directed edge.
Args:
source: Source vertex.
target: Target vertex.
"""
self.graph[source].append(target)
def _dfs(self, source: int, target: int) -> None:
"""Run DFS to determine reachability.
Args:
source: Source vertex.
target: Target vertex.
"""
visited = [False] * self.vertex_count
self._dfs_util(visited, source, target)
def _dfs_util(self, visited: list[bool], source: int, target: int) -> None:
"""Recursive DFS helper.
Args:
visited: Visited flags.
source: Current vertex.
target: Destination vertex.
"""
visited[source] = True
for i in self.graph[source]:
if target in self.graph[source]:
self.has_path = True
return
if not visited[i]:
self._dfs_util(visited, source, i)
def is_reachable(self, source: int, target: int) -> bool:
"""Return True if *target* is reachable from *source*.
Args:
source: Source vertex.
target: Target vertex.
Returns:
True if a directed path exists.
Examples:
>>> g = Graph(2); g.add_edge(0, 1); g.is_reachable(0, 1)
True
"""
self.has_path = False
self._dfs(source, target)
return self.has_path