from collections import deque def parse_input(input_str): lines = input_str.strip().split("\n") graph1 = set() graph2 = set() n, m1 = map(int, lines[:2]) for line in lines[2:2 + m1]: a, b = map(int, line.split()) graph1.add((a, b)) graph1.add((b, a)) m2 = int(lines[2 + m1]) for line in lines[3 + m1:3 + m1 + m2]: a, b = map(int, line.split()) graph2.add((a, b)) graph2.add((b, a)) return graph1, graph2 def find_path(edges, start, end): graph = {node: set() for edge in edges for node in edge} for a, b in edges: graph[a].add(b) graph[b].add(a) queue = deque([(start, [start])]) seen = {start} while queue: current, path = queue.popleft() if current == end: return path for next_node in graph[current]: if next_node not in seen: queue.append((next_node, path + [next_node])) seen.add(next_node) return [] def add_edge_with_triangles(edges, a, b, graph2): path = find_path(edges, a, b) if not path: print("No path found.") return [] operations = [] # Dodaj krawędzie tworzące trójkąty wzdłuż ścieżki if len(path) % 2 == 0: for i in range(0, len(path) - 2, 2): new_edge = (path[i], path[i + 2]) #print(new_edge) # Sprawdź, czy nowa krawędź nie istnieje już w grafie if new_edge not in edges and (new_edge[1], new_edge[0]) not in edges: edges.add(new_edge) edges.add((new_edge[1], new_edge[0])) # Dodawanie w obu kierunkach operations.append(f"+ {new_edge[0]} {new_edge[1]}") else: for i in range(0, len(path) - 2, 2): new_edge = (path[i], path[i + 2]) if new_edge not in edges and (new_edge[1], new_edge[0]) not in edges: edges.add(new_edge) edges.add((new_edge[1], new_edge[0])) #if new_edge in graph2 or (new_edge[1], new_edge[0]) in graph2: operations.append(f"+ {new_edge[0]} {new_edge[1]}") # Dodaj docelową krawędź jeśli jest potrzebna i nie została jeszcze dodana target_edge = (path[0], path[-1]) if target_edge not in edges and (target_edge[1], target_edge[0]) not in edges and (target_edge in graph2 or (target_edge[1], target_edge[0]) in graph2): edges.add(target_edge) edges.add((target_edge[1], target_edge[0])) operations.append(f"+ {target_edge[0]} {target_edge[1]}") return operations def remove_unnecessary_edges(edges, operations, graph2): remove_operations = [] for op in reversed(operations): # Przetwarzaj operacje w odwrotnej kolejności if op.startswith("+"): edge_info = op[2:].split() edge = (int(edge_info[0]), int(edge_info[1])) # Sprawdź, czy krawędź jest tymczasowa (nie ma jej w docelowym grafie) if edge not in graph2 and (edge[1], edge[0]) not in graph2: # Usuń krawędź, jeśli jest tymczasowa edges.remove(edge) edges.remove((edge[1], edge[0])) # Usuwamy w obu kierunkach #print(f"- {edge[0]} {edge[1]}") # Rejestruj operację usunięcia remove_operations.append(f"- {edge[0]} {edge[1]}") return remove_operations def transform_graph(graph1, graph2): all_operations = [] # Dodawanie krawędzi zgodnie z wymaganiami grafu docelowego for edge in graph2: if edge not in graph1: operations = add_edge_with_triangles(graph1, edge[0], edge[1], graph2) all_operations.extend(operations) remove_operations = remove_unnecessary_edges(graph1, all_operations, graph2) all_operations.extend(remove_operations) # Remove edges that are not needed for edge in list(graph1): if edge not in graph2 and (edge[1], edge[0]) not in graph2: graph1.remove(edge) graph1.discard((edge[1], edge[0])) # Usuwamy w obu kierunkach, jeśli istnieje all_operations.append(f"- {edge[0]} {edge[1]}") return all_operations # Input # input_str = """ # 6 # 5 # 1 2 # 2 3 # 3 4 # 4 5 # 5 6 # 6 # 1 2 # 2 3 # 3 4 # 4 5 # 5 6 # 6 1 # """ # get input_str fron user input_str = "" n = input() input_str += n + "\n" ms = input() input_str += ms + "\n" for i in range(int(ms)): input_str += input() + "\n" md = input() input_str += md + "\n" for i in range(int(md)): input_str += input() + "\n" graph1_edges, graph2_edges = parse_input(input_str) operations = transform_graph(graph1_edges, graph2_edges) # Output print(len(operations)) for operation in operations: print(operation)
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | from collections import deque def parse_input(input_str): lines = input_str.strip().split("\n") graph1 = set() graph2 = set() n, m1 = map(int, lines[:2]) for line in lines[2:2 + m1]: a, b = map(int, line.split()) graph1.add((a, b)) graph1.add((b, a)) m2 = int(lines[2 + m1]) for line in lines[3 + m1:3 + m1 + m2]: a, b = map(int, line.split()) graph2.add((a, b)) graph2.add((b, a)) return graph1, graph2 def find_path(edges, start, end): graph = {node: set() for edge in edges for node in edge} for a, b in edges: graph[a].add(b) graph[b].add(a) queue = deque([(start, [start])]) seen = {start} while queue: current, path = queue.popleft() if current == end: return path for next_node in graph[current]: if next_node not in seen: queue.append((next_node, path + [next_node])) seen.add(next_node) return [] def add_edge_with_triangles(edges, a, b, graph2): path = find_path(edges, a, b) if not path: print("No path found.") return [] operations = [] # Dodaj krawędzie tworzące trójkąty wzdłuż ścieżki if len(path) % 2 == 0: for i in range(0, len(path) - 2, 2): new_edge = (path[i], path[i + 2]) #print(new_edge) # Sprawdź, czy nowa krawędź nie istnieje już w grafie if new_edge not in edges and (new_edge[1], new_edge[0]) not in edges: edges.add(new_edge) edges.add((new_edge[1], new_edge[0])) # Dodawanie w obu kierunkach operations.append(f"+ {new_edge[0]} {new_edge[1]}") else: for i in range(0, len(path) - 2, 2): new_edge = (path[i], path[i + 2]) if new_edge not in edges and (new_edge[1], new_edge[0]) not in edges: edges.add(new_edge) edges.add((new_edge[1], new_edge[0])) #if new_edge in graph2 or (new_edge[1], new_edge[0]) in graph2: operations.append(f"+ {new_edge[0]} {new_edge[1]}") # Dodaj docelową krawędź jeśli jest potrzebna i nie została jeszcze dodana target_edge = (path[0], path[-1]) if target_edge not in edges and (target_edge[1], target_edge[0]) not in edges and (target_edge in graph2 or (target_edge[1], target_edge[0]) in graph2): edges.add(target_edge) edges.add((target_edge[1], target_edge[0])) operations.append(f"+ {target_edge[0]} {target_edge[1]}") return operations def remove_unnecessary_edges(edges, operations, graph2): remove_operations = [] for op in reversed(operations): # Przetwarzaj operacje w odwrotnej kolejności if op.startswith("+"): edge_info = op[2:].split() edge = (int(edge_info[0]), int(edge_info[1])) # Sprawdź, czy krawędź jest tymczasowa (nie ma jej w docelowym grafie) if edge not in graph2 and (edge[1], edge[0]) not in graph2: # Usuń krawędź, jeśli jest tymczasowa edges.remove(edge) edges.remove((edge[1], edge[0])) # Usuwamy w obu kierunkach #print(f"- {edge[0]} {edge[1]}") # Rejestruj operację usunięcia remove_operations.append(f"- {edge[0]} {edge[1]}") return remove_operations def transform_graph(graph1, graph2): all_operations = [] # Dodawanie krawędzi zgodnie z wymaganiami grafu docelowego for edge in graph2: if edge not in graph1: operations = add_edge_with_triangles(graph1, edge[0], edge[1], graph2) all_operations.extend(operations) remove_operations = remove_unnecessary_edges(graph1, all_operations, graph2) all_operations.extend(remove_operations) # Remove edges that are not needed for edge in list(graph1): if edge not in graph2 and (edge[1], edge[0]) not in graph2: graph1.remove(edge) graph1.discard((edge[1], edge[0])) # Usuwamy w obu kierunkach, jeśli istnieje all_operations.append(f"- {edge[0]} {edge[1]}") return all_operations # Input # input_str = """ # 6 # 5 # 1 2 # 2 3 # 3 4 # 4 5 # 5 6 # 6 # 1 2 # 2 3 # 3 4 # 4 5 # 5 6 # 6 1 # """ # get input_str fron user input_str = "" n = input() input_str += n + "\n" ms = input() input_str += ms + "\n" for i in range(int(ms)): input_str += input() + "\n" md = input() input_str += md + "\n" for i in range(int(md)): input_str += input() + "\n" graph1_edges, graph2_edges = parse_input(input_str) operations = transform_graph(graph1_edges, graph2_edges) # Output print(len(operations)) for operation in operations: print(operation) |