|
| 1 | +import sys |
| 2 | +from collections import namedtuple |
| 3 | + |
| 4 | +Edge = namedtuple('Edge', ['v', 'w']) |
| 5 | + |
| 6 | +class Directed_Acyclic_Graph: |
| 7 | + def __init__(self, source, sink, edges): |
| 8 | + |
| 9 | + self.v_no_label_gap = source #v_no are 0-based index but input labels could start at any position |
| 10 | + self.vertices_count = sink - source + 1 |
| 11 | + self.is_valid_dag = True |
| 12 | + |
| 13 | + self.build_adjacency_list(edges) |
| 14 | + self.check_dag_dfs() |
| 15 | + |
| 16 | + #print(self.adjacency_list) |
| 17 | + #print("self.is_valid_source: ", self.is_valid_source) |
| 18 | + #print("self.is_valid_sink: ", self.is_valid_sink) |
| 19 | + #print("self.is_valid_dag: ", self.is_valid_dag) |
| 20 | + |
| 21 | + def build_adjacency_list(self, edges): |
| 22 | + |
| 23 | + self.adjacency_list = [[] for _ in range(self.vertices_count)] |
| 24 | + |
| 25 | + self.is_valid_source = True |
| 26 | + self.is_valid_sink = False |
| 27 | + for edge in edges: |
| 28 | + u = int(edge.split("->")[0]) - self.v_no_label_gap |
| 29 | + v = int(edge.split("->")[1].split(":")[0]) - self.v_no_label_gap |
| 30 | + w = int(edge.split("->")[1].split(":")[1]) |
| 31 | + |
| 32 | + self.adjacency_list[u].append(Edge(v, w)) |
| 33 | + |
| 34 | + self.is_valid_source &= (v != 0) |
| 35 | + self.is_valid_sink |= (v == self.vertices_count - 1) |
| 36 | + |
| 37 | + #print(self.adjacency_list) |
| 38 | + |
| 39 | + self.is_valid_source &= (len(self.adjacency_list[0]) > 0) |
| 40 | + self.is_valid_sink &= len(self.adjacency_list[self.vertices_count - 1]) == 0 |
| 41 | + |
| 42 | + def explore_path(self, u, visited, cycle): |
| 43 | + |
| 44 | + visited[u] = True |
| 45 | + cycle[u] = True |
| 46 | + for edge in self.adjacency_list[u]: |
| 47 | + |
| 48 | + if cycle[edge.v]: |
| 49 | + return True |
| 50 | + |
| 51 | + if visited[edge.v]: |
| 52 | + continue |
| 53 | + |
| 54 | + if self.explore_path(edge.v, visited, cycle): |
| 55 | + return True |
| 56 | + |
| 57 | + cycle[u] = False |
| 58 | + |
| 59 | + return False |
| 60 | + |
| 61 | + def check_dag_dfs(self): |
| 62 | + |
| 63 | + visited = [False for _ in range(self.vertices_count)] |
| 64 | + cycle = [False for _ in range(self.vertices_count)] |
| 65 | + |
| 66 | + self.is_valid_dag = True |
| 67 | + for v in range(self.vertices_count): |
| 68 | + if not visited[v]: |
| 69 | + if self.explore_path(v, visited, cycle): |
| 70 | + self.is_valid_dag = False |
| 71 | + break |
| 72 | + |
| 73 | + def compute_longest_path(self, source, sink): |
| 74 | + self.longest_path_len = 0 |
| 75 | + self.longest_path = [] |
| 76 | + |
| 77 | + if not self.is_valid_dag: |
| 78 | + return |
| 79 | + |
| 80 | + # TODO: your code here |
| 81 | + return "" |
| 82 | + |
| 83 | + def longest_path_to_str(self): |
| 84 | + |
| 85 | + return '->'.join(self.longest_path) |
| 86 | + |
| 87 | +if __name__ == "__main__": |
| 88 | + |
| 89 | + source = int(sys.stdin.readline().strip()) |
| 90 | + sink = int(sys.stdin.readline().strip()) |
| 91 | + edges = [line.strip() for line in sys.stdin] |
| 92 | + |
| 93 | + dag = Directed_Acyclic_Graph(source, sink, edges) |
| 94 | + dag.compute_longest_path(source, sink) |
| 95 | + |
| 96 | + print(dag.longest_path_len) |
| 97 | + #print(dag.longest_path_to_str) |
0 commit comments