def find_path_with_capacity_dfs(graph: DirectedGraph, current_node, end_node, visited, flows: Dict): """ Finds a path with available capacity from current node to end node Returns none if no such paths exist """ visited.add(current_node) for edge in graph.get_edges(current_node): origin, destination = (edge.a, edge.b) if edge.a == current_node else (edge.b, edge.a) if (edge.weight > flows[edge] and edge.a == current_node) or (0 < flows[edge] and edge.b == current_node): if destination in visited: continue if destination == end_node: return [edge] result = find_path_with_capacity_dfs(graph, destination, end_node, visited, flows) if result: return [edge] + result visited.remove(current_node)
def topological_sort(graph: DirectedGraph) -> List: """ Called Kahns algorithm Sorts the vertices of a graph in a topological order or raises an exception when the graph is cyclical :param graph: The graph to be sorted toplogically """ graph = copy.deepcopy(graph) sorted_nodes = [] nodes = Queue() # Add the nodes without incoming edges to the starting nodes for vertex in graph.get_vertices(): if not graph.has_incoming_edge(vertex): nodes.enqueue(vertex) # Keep removing nodes and edges while nodes with no incoming edges exist while not nodes.is_empty(): node = nodes.dequeue() sorted_nodes.append(node) for edge in graph.get_edges(node)[:]: graph.delete_edge(edge.a, edge.b) if not graph.has_incoming_edge(edge.b): nodes.enqueue(edge.b) if len(list(graph.get_all_edges())): raise RuntimeError('Graph is cyclical') return sorted_nodes