#include <algorithm> #include <iostream> #include <queue> #include <set> #include <vector> using namespace std; struct Edge { int from, to; Edge(int from, int to) : from(min(from, to)), to(max(from, to)) {} bool operator<(const Edge& rhs) const { if (from != rhs.from) return from < rhs.from; return to < rhs.to; } }; struct Graph { int n, m; vector<vector<int>> nodes; set<Edge> edges; void add_edge(int a, int b) { a--; b--; nodes[a].push_back(b); nodes[b].push_back(a); edges.insert(Edge(a, b)); } }; struct TestCase { Graph src_graph; Graph dst_graph; }; TestCase read_test_case() { TestCase tc; int n, m1, m2; cin >> n; cin >> m1; tc.src_graph.n = n; tc.src_graph.m = m1; tc.src_graph.nodes.resize(n); for (int _ = 0; _ < m1; _++) { int a, b; cin >> a >> b; tc.src_graph.add_edge(a, b); } cin >> m2; tc.dst_graph.n = n; tc.dst_graph.m = m2; tc.dst_graph.nodes.resize(n); for (int _ = 0; _ < m2; _++) { int a, b; cin >> a >> b; tc.dst_graph.add_edge(a, b); } return tc; } void solve_test_case(TestCase tc); int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); solve_test_case(read_test_case()); } vector<int> node_order(const Graph& graph) { vector<bool> visited(graph.n, false); vector<int> order; queue<int> q; q.push(0); while (!q.empty()) { auto current = q.front(); q.pop(); if (current != 0) order.push_back(current); for (auto n : graph.nodes[current]) { if (visited[n]) continue; visited[n] = true; q.push(n); } } return order; } struct Action { enum Type { ADD, REMOVE } type; Edge edge; }; void solve_test_case(TestCase tc) { auto add_order = node_order(tc.src_graph); auto remove_order = node_order(tc.dst_graph); reverse(remove_order.begin(), remove_order.end()); set<Edge> edges = tc.src_graph.edges; vector<Action> actions; for (auto x : add_order) { if (edges.contains({0, x})) continue; edges.insert({0, x}); actions.push_back({Action::ADD, {1, x + 1}}); } for (const auto e : tc.dst_graph.edges) { if (edges.contains(e)) continue; actions.push_back({Action::ADD, {e.from + 1, e.to + 1}}); } for (const auto e : edges) { if (e.from == 0) continue; if (tc.dst_graph.edges.contains(e)) continue; actions.push_back({Action::REMOVE, {e.from + 1, e.to + 1}}); } for (auto x : remove_order) { if (tc.dst_graph.edges.contains({0, x})) continue; actions.push_back({Action::REMOVE, {1, x + 1}}); } cout << actions.size() << "\n"; for (const auto& [type, edge] : actions) { switch (type) { case Action::ADD: cout << "+ " << edge.from << " " << edge.to << "\n"; break; case Action::REMOVE: cout << "- " << edge.from << " " << edge.to << "\n"; break; } } }
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 | #include <algorithm> #include <iostream> #include <queue> #include <set> #include <vector> using namespace std; struct Edge { int from, to; Edge(int from, int to) : from(min(from, to)), to(max(from, to)) {} bool operator<(const Edge& rhs) const { if (from != rhs.from) return from < rhs.from; return to < rhs.to; } }; struct Graph { int n, m; vector<vector<int>> nodes; set<Edge> edges; void add_edge(int a, int b) { a--; b--; nodes[a].push_back(b); nodes[b].push_back(a); edges.insert(Edge(a, b)); } }; struct TestCase { Graph src_graph; Graph dst_graph; }; TestCase read_test_case() { TestCase tc; int n, m1, m2; cin >> n; cin >> m1; tc.src_graph.n = n; tc.src_graph.m = m1; tc.src_graph.nodes.resize(n); for (int _ = 0; _ < m1; _++) { int a, b; cin >> a >> b; tc.src_graph.add_edge(a, b); } cin >> m2; tc.dst_graph.n = n; tc.dst_graph.m = m2; tc.dst_graph.nodes.resize(n); for (int _ = 0; _ < m2; _++) { int a, b; cin >> a >> b; tc.dst_graph.add_edge(a, b); } return tc; } void solve_test_case(TestCase tc); int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); solve_test_case(read_test_case()); } vector<int> node_order(const Graph& graph) { vector<bool> visited(graph.n, false); vector<int> order; queue<int> q; q.push(0); while (!q.empty()) { auto current = q.front(); q.pop(); if (current != 0) order.push_back(current); for (auto n : graph.nodes[current]) { if (visited[n]) continue; visited[n] = true; q.push(n); } } return order; } struct Action { enum Type { ADD, REMOVE } type; Edge edge; }; void solve_test_case(TestCase tc) { auto add_order = node_order(tc.src_graph); auto remove_order = node_order(tc.dst_graph); reverse(remove_order.begin(), remove_order.end()); set<Edge> edges = tc.src_graph.edges; vector<Action> actions; for (auto x : add_order) { if (edges.contains({0, x})) continue; edges.insert({0, x}); actions.push_back({Action::ADD, {1, x + 1}}); } for (const auto e : tc.dst_graph.edges) { if (edges.contains(e)) continue; actions.push_back({Action::ADD, {e.from + 1, e.to + 1}}); } for (const auto e : edges) { if (e.from == 0) continue; if (tc.dst_graph.edges.contains(e)) continue; actions.push_back({Action::REMOVE, {e.from + 1, e.to + 1}}); } for (auto x : remove_order) { if (tc.dst_graph.edges.contains({0, x})) continue; actions.push_back({Action::REMOVE, {1, x + 1}}); } cout << actions.size() << "\n"; for (const auto& [type, edge] : actions) { switch (type) { case Action::ADD: cout << "+ " << edge.from << " " << edge.to << "\n"; break; case Action::REMOVE: cout << "- " << edge.from << " " << edge.to << "\n"; break; } } } |