#include <bits/stdc++.h> using namespace std; #define FOR(i, lower, upper) for(int (i) = (lower); i <= (int)(upper); (i)++) #define FORD(i, upper, lower) for(int (i) = (upper); i >= (int)(lower); (i)--) const int N = 3e4; struct op { char type; int u; int v; }; struct path { int to; int len; }; bool cmp1(path p1, path p2) { return p1.len < p2.len; } bool cmp2(path p1, path p2) { return p1.len > p2.len; } int n, m, mt; vector<int> g[N + 1]; vector<int> gt[N + 1]; bool vis[N + 1]; set<pair<int, int>> E, Et; vector<op> ans; path P[N + 1]; void BFS(int s, vector<int> g[]) { queue<int> q; vis[s] = 1; q.push(s); P[s] = {s, 0}; while(q.size()) { int u = q.front(); q.pop(); for(int v : g[u]) { if(!vis[v]) { vis[v] = 1; q.push(v); P[v] = {v, P[u].len + 1}; } } } } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m; FOR(i, 1, m) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); E.insert({u, v}); E.insert({v, u}); } cin >> mt; FOR(i, 1, mt) { int u, v; cin >> u >> v; gt[u].push_back(v); gt[v].push_back(u); Et.insert({u, v}); Et.insert({v, u}); } /// stworzenie super-korzenia BFS(1, g); sort(P + 1, P + 1 + n, cmp1); FOR(i, 1, n) { if(P[i].len < 2) continue; E.insert({1, P[i].to}); E.insert({P[i].to, 1}); ans.push_back({'+', 1, P[i].to}); } /// dodanie brakujacych krawedzi for(pair<int, int> e : Et) { if(E.find(e) == E.end()) { E.insert(e); E.insert({e.second, e.first}); ans.push_back({'+', e.first, e.second}); } } /// usuniecie nadmiarowych krawedzi niewiarzacych korzenia set<pair<int, int>> ig; for(pair<int, int> e : E) { if(e.first != 1 && e.second != 1 && ig.find(e) == ig.end() && Et.find(e) == Et.end()) { ig.insert(e); ig.insert({e.second, e.first}); ans.push_back({'-', e.first, e.second}); } } /// teraz g = gt + (1, v), kolejnosc usuwania odwrotna do kolejnosci tworzenia superkorzenia dla gt FOR(i, 1, n) vis[i] = 0; BFS(1, gt); sort(P + 1, P + 1 + n, cmp2); FOR(i, 1, n) { if(P[i].len < 2) break; if(Et.find({1, P[i].to}) == Et.end()) { ans.push_back({'-', 1, P[i].to}); } } cout << ans.size() << '\n'; for(op o : ans) { cout << o.type << ' ' << o.u << ' ' << o.v << '\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 | #include <bits/stdc++.h> using namespace std; #define FOR(i, lower, upper) for(int (i) = (lower); i <= (int)(upper); (i)++) #define FORD(i, upper, lower) for(int (i) = (upper); i >= (int)(lower); (i)--) const int N = 3e4; struct op { char type; int u; int v; }; struct path { int to; int len; }; bool cmp1(path p1, path p2) { return p1.len < p2.len; } bool cmp2(path p1, path p2) { return p1.len > p2.len; } int n, m, mt; vector<int> g[N + 1]; vector<int> gt[N + 1]; bool vis[N + 1]; set<pair<int, int>> E, Et; vector<op> ans; path P[N + 1]; void BFS(int s, vector<int> g[]) { queue<int> q; vis[s] = 1; q.push(s); P[s] = {s, 0}; while(q.size()) { int u = q.front(); q.pop(); for(int v : g[u]) { if(!vis[v]) { vis[v] = 1; q.push(v); P[v] = {v, P[u].len + 1}; } } } } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m; FOR(i, 1, m) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); E.insert({u, v}); E.insert({v, u}); } cin >> mt; FOR(i, 1, mt) { int u, v; cin >> u >> v; gt[u].push_back(v); gt[v].push_back(u); Et.insert({u, v}); Et.insert({v, u}); } /// stworzenie super-korzenia BFS(1, g); sort(P + 1, P + 1 + n, cmp1); FOR(i, 1, n) { if(P[i].len < 2) continue; E.insert({1, P[i].to}); E.insert({P[i].to, 1}); ans.push_back({'+', 1, P[i].to}); } /// dodanie brakujacych krawedzi for(pair<int, int> e : Et) { if(E.find(e) == E.end()) { E.insert(e); E.insert({e.second, e.first}); ans.push_back({'+', e.first, e.second}); } } /// usuniecie nadmiarowych krawedzi niewiarzacych korzenia set<pair<int, int>> ig; for(pair<int, int> e : E) { if(e.first != 1 && e.second != 1 && ig.find(e) == ig.end() && Et.find(e) == Et.end()) { ig.insert(e); ig.insert({e.second, e.first}); ans.push_back({'-', e.first, e.second}); } } /// teraz g = gt + (1, v), kolejnosc usuwania odwrotna do kolejnosci tworzenia superkorzenia dla gt FOR(i, 1, n) vis[i] = 0; BFS(1, gt); sort(P + 1, P + 1 + n, cmp2); FOR(i, 1, n) { if(P[i].len < 2) break; if(Et.find({1, P[i].to}) == Et.end()) { ans.push_back({'-', 1, P[i].to}); } } cout << ans.size() << '\n'; for(op o : ans) { cout << o.type << ' ' << o.u << ' ' << o.v << '\n'; } return 0; } |