#include <iostream> #include <vector> #include <functional> #include <queue> #include <utility> #include <set> #include <algorithm> int main() { std::ios_base::sync_with_stdio(0); std::cin.tie(0); std::cin.tie(0); int N; std::cin >> N; std::vector<std::vector<int>> G1(N); auto G2 = G1; std::set<std::pair<int, int>> current_edges, final_edges; std::vector<std::tuple<char, int, int>> moves; auto exists = [&](auto &edges, int a, int b) { return edges.find(std::minmax(a, b)) != edges.end(); }; auto add_edge = [&](int a, int b) { current_edges.insert(std::minmax(a, b)); moves.push_back({'+', a+1, b+1}); }; auto remove_edge = [&](int a, int b) { current_edges.erase(std::minmax(a, b)); moves.push_back({'-', a+1, b+1}); }; auto input_G = [&](auto &G, auto &edges) { int M; std::cin >> M; while(M--) { int a, b; std::cin >> a >> b; a--, b--; G[a].push_back(b); G[b].push_back(a); edges.insert(std::minmax(a, b)); } }; input_G(G1, current_edges); input_G(G2, final_edges); auto prep = [&]() { std::queue<int> Q; std::vector<int> dist(N, -1); Q.push(0); dist[0] = 0; while(Q.size() > 0) { int v = Q.front(); Q.pop(); for(int u : G1[v]) { if(dist[u] == -1) { dist[u] = dist[v] + 1; Q.push(u); if(!exists(current_edges, 0, u)) { add_edge(0, u); } } } } }; prep(); for(auto [a, b] : final_edges) { if(!exists(current_edges, a, b)) { add_edge(a, b); } } auto remove_excess = [&]() { std::vector<std::pair<int, int>> to_remove; for(auto [a, b] : current_edges) { if(a == 0) { continue; } if(exists(final_edges, a, b)) { continue; } to_remove.push_back({a, b}); } for(auto [a, b] : to_remove) { remove_edge(a, b); } }; remove_excess(); auto remove_spanning_tree = [&]() { std::queue<int> Q; std::vector<int> dist(N, -1); std::vector<int> order; Q.push(0); dist[0] = 0; while(Q.size() > 0) { int v = Q.front(); Q.pop(); order.push_back(v); for(int u : G2[v]) { if(dist[u] == -1) { dist[u] = dist[v] + 1; Q.push(u); } } } while(order.size() > 1) { int v = order.back(); order.pop_back(); if(exists(final_edges, 0, v)) { continue; } remove_edge(0, v); } }; remove_spanning_tree(); std::cout << moves.size() << '\n'; for(auto [c, a, b] : moves) { std::cout << c << ' ' << a << ' ' << b << '\n'; } 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 | #include <iostream> #include <vector> #include <functional> #include <queue> #include <utility> #include <set> #include <algorithm> int main() { std::ios_base::sync_with_stdio(0); std::cin.tie(0); std::cin.tie(0); int N; std::cin >> N; std::vector<std::vector<int>> G1(N); auto G2 = G1; std::set<std::pair<int, int>> current_edges, final_edges; std::vector<std::tuple<char, int, int>> moves; auto exists = [&](auto &edges, int a, int b) { return edges.find(std::minmax(a, b)) != edges.end(); }; auto add_edge = [&](int a, int b) { current_edges.insert(std::minmax(a, b)); moves.push_back({'+', a+1, b+1}); }; auto remove_edge = [&](int a, int b) { current_edges.erase(std::minmax(a, b)); moves.push_back({'-', a+1, b+1}); }; auto input_G = [&](auto &G, auto &edges) { int M; std::cin >> M; while(M--) { int a, b; std::cin >> a >> b; a--, b--; G[a].push_back(b); G[b].push_back(a); edges.insert(std::minmax(a, b)); } }; input_G(G1, current_edges); input_G(G2, final_edges); auto prep = [&]() { std::queue<int> Q; std::vector<int> dist(N, -1); Q.push(0); dist[0] = 0; while(Q.size() > 0) { int v = Q.front(); Q.pop(); for(int u : G1[v]) { if(dist[u] == -1) { dist[u] = dist[v] + 1; Q.push(u); if(!exists(current_edges, 0, u)) { add_edge(0, u); } } } } }; prep(); for(auto [a, b] : final_edges) { if(!exists(current_edges, a, b)) { add_edge(a, b); } } auto remove_excess = [&]() { std::vector<std::pair<int, int>> to_remove; for(auto [a, b] : current_edges) { if(a == 0) { continue; } if(exists(final_edges, a, b)) { continue; } to_remove.push_back({a, b}); } for(auto [a, b] : to_remove) { remove_edge(a, b); } }; remove_excess(); auto remove_spanning_tree = [&]() { std::queue<int> Q; std::vector<int> dist(N, -1); std::vector<int> order; Q.push(0); dist[0] = 0; while(Q.size() > 0) { int v = Q.front(); Q.pop(); order.push_back(v); for(int u : G2[v]) { if(dist[u] == -1) { dist[u] = dist[v] + 1; Q.push(u); } } } while(order.size() > 1) { int v = order.back(); order.pop_back(); if(exists(final_edges, 0, v)) { continue; } remove_edge(0, v); } }; remove_spanning_tree(); std::cout << moves.size() << '\n'; for(auto [c, a, b] : moves) { std::cout << c << ' ' << a << ' ' << b << '\n'; } return 0; } |