#include<bits/stdc++.h> #define FOR(i,s,e) for(int i=(s); i<=(e); i++) #define FORD(i,s,e) for(int i=(s); i>=(e); i--) #define ALL(k) (k).begin(), (k).end() #define e1 first #define e2 second #define mp make_pair using namespace std; using LL=long long; using LD=long double; using PII=pair<int,int>; const int MAXN = 30111; vector<int> initial_edges[MAXN]; vector<int> final_edges[MAXN]; vector<pair<char, PII>> moves; int vis[MAXN]; vector<int> dfs_order; void dfs(int v, bool use_initial_edges=true){ dfs_order.push_back(v); auto edges = use_initial_edges ? &(initial_edges) : &(final_edges); for (auto &b: (*edges)[v]){ if (!vis[b]){ vis[b] = 1; dfs(b); } } } int main(){ int n; scanf("%d",&n); int ms; scanf("%d", &ms); set<PII> existing_edges; FOR(i,1,ms){ int a, b; scanf("%d%d", &a,&b); if (a > b){ swap(a,b); } // printf("Initial edge %d %d\n", a,b); initial_edges[a].push_back(b); initial_edges[b].push_back(a); existing_edges.insert(mp(a,b)); } int md; scanf("%d",&md); set<PII> target_edges; FOR(i,1,md){ int a,b; scanf("%d%d", &a, &b); if (a > b){ swap(a,b); } // printf("Final edge %d %d\n", a, b); final_edges[a].push_back(b); final_edges[b].push_back(a); target_edges.insert(mp(a,b)); } vis[1] = 1; dfs(1, true); set<int> one_initial_edges; for(auto b: initial_edges[1]){ one_initial_edges.insert(b); } for (auto v: dfs_order){ // printf("DFS order: %d\n", v); if (v != 1 && one_initial_edges.find(v) == one_initial_edges.end()){ moves.emplace_back('+', mp(1, v)); existing_edges.insert(mp(1,v)); } } for (auto edge : existing_edges){ int a = edge.e1, b = edge.e2; if (a == 1){ continue; // we'll deal with it later } if (target_edges.find(edge) == target_edges.end()){ moves.emplace_back('-', mp(a, b)); } } FOR(i,1,n){ vis[i] = 0; } dfs_order.clear(); vis[1] = 1; dfs(1, false); reverse(ALL(dfs_order)); for(auto &v: dfs_order){ // printf("Reversed final DFS order %d\n", v); if (v != 1 && target_edges.find(mp(1,v)) == target_edges.end()){ moves.emplace_back('-', mp(1, v)); } } printf("%d\n", moves.size()); for(auto &move: moves){ char t = move.e1; int a = move.e2.e1, b = move.e2.e2; printf("%c %d %d\n", t, a, b); } } //1. take any node (atom) eg. 1 //2. connect node 1 to all other nodes (decide on order // using dfs from that node) [30,000 moves] //3. transform the remainder of the graph using 1 // as connector [100,000 moves] //4. unwind the connections of node 1 (use DFS // on the *new* target graph to set order) [30,000 moves]
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 | #include<bits/stdc++.h> #define FOR(i,s,e) for(int i=(s); i<=(e); i++) #define FORD(i,s,e) for(int i=(s); i>=(e); i--) #define ALL(k) (k).begin(), (k).end() #define e1 first #define e2 second #define mp make_pair using namespace std; using LL=long long; using LD=long double; using PII=pair<int,int>; const int MAXN = 30111; vector<int> initial_edges[MAXN]; vector<int> final_edges[MAXN]; vector<pair<char, PII>> moves; int vis[MAXN]; vector<int> dfs_order; void dfs(int v, bool use_initial_edges=true){ dfs_order.push_back(v); auto edges = use_initial_edges ? &(initial_edges) : &(final_edges); for (auto &b: (*edges)[v]){ if (!vis[b]){ vis[b] = 1; dfs(b); } } } int main(){ int n; scanf("%d",&n); int ms; scanf("%d", &ms); set<PII> existing_edges; FOR(i,1,ms){ int a, b; scanf("%d%d", &a,&b); if (a > b){ swap(a,b); } // printf("Initial edge %d %d\n", a,b); initial_edges[a].push_back(b); initial_edges[b].push_back(a); existing_edges.insert(mp(a,b)); } int md; scanf("%d",&md); set<PII> target_edges; FOR(i,1,md){ int a,b; scanf("%d%d", &a, &b); if (a > b){ swap(a,b); } // printf("Final edge %d %d\n", a, b); final_edges[a].push_back(b); final_edges[b].push_back(a); target_edges.insert(mp(a,b)); } vis[1] = 1; dfs(1, true); set<int> one_initial_edges; for(auto b: initial_edges[1]){ one_initial_edges.insert(b); } for (auto v: dfs_order){ // printf("DFS order: %d\n", v); if (v != 1 && one_initial_edges.find(v) == one_initial_edges.end()){ moves.emplace_back('+', mp(1, v)); existing_edges.insert(mp(1,v)); } } for (auto edge : existing_edges){ int a = edge.e1, b = edge.e2; if (a == 1){ continue; // we'll deal with it later } if (target_edges.find(edge) == target_edges.end()){ moves.emplace_back('-', mp(a, b)); } } FOR(i,1,n){ vis[i] = 0; } dfs_order.clear(); vis[1] = 1; dfs(1, false); reverse(ALL(dfs_order)); for(auto &v: dfs_order){ // printf("Reversed final DFS order %d\n", v); if (v != 1 && target_edges.find(mp(1,v)) == target_edges.end()){ moves.emplace_back('-', mp(1, v)); } } printf("%d\n", moves.size()); for(auto &move: moves){ char t = move.e1; int a = move.e2.e1, b = move.e2.e2; printf("%c %d %d\n", t, a, b); } } //1. take any node (atom) eg. 1 //2. connect node 1 to all other nodes (decide on order // using dfs from that node) [30,000 moves] //3. transform the remainder of the graph using 1 // as connector [100,000 moves] //4. unwind the connections of node 1 (use DFS // on the *new* target graph to set order) [30,000 moves] |