#include <iostream> #include <vector> #include <set> #include <algorithm> using namespace std; typedef int AtomNr; typedef pair<AtomNr, AtomNr> Connection; typedef pair<char, Connection> Operation; struct Graph { int n; vector<set<AtomNr>> atom_to_connected; Graph(int _n) : n(_n), atom_to_connected(_n + 1) {} void add_connection(AtomNr a, AtomNr b) { atom_to_connected[a].insert(b); atom_to_connected[b].insert(a); } bool is_connection_present(AtomNr a, AtomNr b) const { return atom_to_connected[a].find(b) != atom_to_connected[a].end(); } bool is_connection_present(const Connection& conn) const { return is_connection_present(conn.first, conn.second); } vector<Connection> get_connections(AtomNr minimal_nr = 1) const { vector<Connection> connections; for (AtomNr i = minimal_nr; i <= n; ++i) { for (auto j: atom_to_connected[i]) { if (i < j) { connections.push_back(Connection(i, j)); } } } return connections; } vector<AtomNr> bfs(AtomNr start_vertex = 1) { vector<AtomNr> queue = {start_vertex}; set<AtomNr> visited = {start_vertex}; for (size_t i = 0; i < queue.size(); ++i) { AtomNr a = queue[i]; for (AtomNr b: atom_to_connected[a]) { if (visited.find(b) == visited.end()) { queue.push_back(b); visited.insert(b); } } } return queue; } }; ostream& operator<<(ostream& out, const Graph& g) { vector<Connection> connections = g.get_connections(); out << "Vertices: " << g.n << ", " << "Edges: " << connections.size() << endl; for (auto conn: connections) { out << conn.first << "<->" << conn.second << endl; } return out; } template <typename T> ostream& operator<<(ostream& out, const vector<T>& vec) { out << "[ "; for (auto v: vec) out << v << ", "; out << "]"; return out; } void read_graph(Graph& g) { int m; cin >> m; for (int i = 0; i < m; ++i) { int a, b; cin >> a >> b; g.add_connection(a, b); } } int main() { ios_base::sync_with_stdio(0); int n; cin >> n; Graph original_graph(n), target_graph(n); read_graph(original_graph); read_graph(target_graph); // cout << "Original graph" << endl << original_graph << original_graph.bfs() << endl << endl; // cout << "Target graph" << endl << target_graph << target_graph.bfs() << endl; vector<Operation> operations; // connect 1 with all other atoms vector<AtomNr> original_one_queue = original_graph.bfs(); for (auto it = original_one_queue.begin(); it != original_one_queue.end(); ++it) { AtomNr a = *it; if (a != 1 && !original_graph.is_connection_present(1, a)) { operations.push_back(Operation('+', Connection(1, a))); } } // add target connections (except 1- connections) that are not present in original graph vector<Connection> target_connections = target_graph.get_connections(2); for (Connection conn: target_connections) { if (!original_graph.is_connection_present(conn)) { operations.push_back(Operation('+', conn)); } } // remove connections (except 1- connections) that are present in original but not in target graph vector<Connection> original_connections = original_graph.get_connections(2); for (Connection conn: original_connections) { if (!target_graph.is_connection_present(conn)) { operations.push_back(Operation('-', conn)); } } // remove undesired 1- connections vector<AtomNr> target_one_queue = target_graph.bfs(); for (auto it = target_one_queue.rbegin(); it != target_one_queue.rend(); ++it) { AtomNr a = *it; if (a != 1 && !target_graph.is_connection_present(1, a)) { operations.push_back(Operation('-', Connection(1, a))); } } cout << operations.size() << endl; for (Operation op: operations) { cout << op.first << " " << op.second.first << " " << op.second.second << endl; } return 0; }
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 | #include <iostream> #include <vector> #include <set> #include <algorithm> using namespace std; typedef int AtomNr; typedef pair<AtomNr, AtomNr> Connection; typedef pair<char, Connection> Operation; struct Graph { int n; vector<set<AtomNr>> atom_to_connected; Graph(int _n) : n(_n), atom_to_connected(_n + 1) {} void add_connection(AtomNr a, AtomNr b) { atom_to_connected[a].insert(b); atom_to_connected[b].insert(a); } bool is_connection_present(AtomNr a, AtomNr b) const { return atom_to_connected[a].find(b) != atom_to_connected[a].end(); } bool is_connection_present(const Connection& conn) const { return is_connection_present(conn.first, conn.second); } vector<Connection> get_connections(AtomNr minimal_nr = 1) const { vector<Connection> connections; for (AtomNr i = minimal_nr; i <= n; ++i) { for (auto j: atom_to_connected[i]) { if (i < j) { connections.push_back(Connection(i, j)); } } } return connections; } vector<AtomNr> bfs(AtomNr start_vertex = 1) { vector<AtomNr> queue = {start_vertex}; set<AtomNr> visited = {start_vertex}; for (size_t i = 0; i < queue.size(); ++i) { AtomNr a = queue[i]; for (AtomNr b: atom_to_connected[a]) { if (visited.find(b) == visited.end()) { queue.push_back(b); visited.insert(b); } } } return queue; } }; ostream& operator<<(ostream& out, const Graph& g) { vector<Connection> connections = g.get_connections(); out << "Vertices: " << g.n << ", " << "Edges: " << connections.size() << endl; for (auto conn: connections) { out << conn.first << "<->" << conn.second << endl; } return out; } template <typename T> ostream& operator<<(ostream& out, const vector<T>& vec) { out << "[ "; for (auto v: vec) out << v << ", "; out << "]"; return out; } void read_graph(Graph& g) { int m; cin >> m; for (int i = 0; i < m; ++i) { int a, b; cin >> a >> b; g.add_connection(a, b); } } int main() { ios_base::sync_with_stdio(0); int n; cin >> n; Graph original_graph(n), target_graph(n); read_graph(original_graph); read_graph(target_graph); // cout << "Original graph" << endl << original_graph << original_graph.bfs() << endl << endl; // cout << "Target graph" << endl << target_graph << target_graph.bfs() << endl; vector<Operation> operations; // connect 1 with all other atoms vector<AtomNr> original_one_queue = original_graph.bfs(); for (auto it = original_one_queue.begin(); it != original_one_queue.end(); ++it) { AtomNr a = *it; if (a != 1 && !original_graph.is_connection_present(1, a)) { operations.push_back(Operation('+', Connection(1, a))); } } // add target connections (except 1- connections) that are not present in original graph vector<Connection> target_connections = target_graph.get_connections(2); for (Connection conn: target_connections) { if (!original_graph.is_connection_present(conn)) { operations.push_back(Operation('+', conn)); } } // remove connections (except 1- connections) that are present in original but not in target graph vector<Connection> original_connections = original_graph.get_connections(2); for (Connection conn: original_connections) { if (!target_graph.is_connection_present(conn)) { operations.push_back(Operation('-', conn)); } } // remove undesired 1- connections vector<AtomNr> target_one_queue = target_graph.bfs(); for (auto it = target_one_queue.rbegin(); it != target_one_queue.rend(); ++it) { AtomNr a = *it; if (a != 1 && !target_graph.is_connection_present(1, a)) { operations.push_back(Operation('-', Connection(1, a))); } } cout << operations.size() << endl; for (Operation op: operations) { cout << op.first << " " << op.second.first << " " << op.second.second << endl; } return 0; } |