#include <bits/stdc++.h>
using namespace std;
struct node {
int id = 0;
set<node*> neigh = {};
int visited = 0;
static void insert(node* a, node* b) {
a->neigh.insert(b);
b->neigh.insert(a);
}
static void erase(node* a, node* b) {
a->neigh.erase(b);
b->neigh.erase(a);
}
};
typedef pair<node*, node*> edge;
struct change {
pair<int, int> edge;
bool remove;
};
void createOneEdges(node* one, node* root, int visited, set<int>& existing, vector<change>& moves);
void eraseOneEdges(node* one, node* root, int visited, set<int>& toKeep, vector<change>& moves);
int main() {
int n;
scanf(" %d", &n);
vector<node> nodes(n);
for (int i = 0; i < n; i++) {
nodes[i].id = i+1;
}
set<pair<int, int>> toInsert;
set<pair<int, int>> toErase;
set<int> oneEdgesKeep;
set<int> oneEdgesExist;
int e;
scanf(" %d", &e);
for (int i = 0; i < e; i++) {
int a, b;
scanf(" %d %d", &a, &b);
if (a > b) swap(a,b);
node::insert(&nodes[a-1],&nodes[b-1]);
if (a == 1) {
oneEdgesExist.insert(b);
} else {
toErase.insert({a,b});
}
}
scanf(" %d", &e);
for (int i = 0; i < e; i++) {
int a, b;
scanf(" %d %d", &a, &b);
if (a > b) swap(a,b);
if (a == 1) {
oneEdgesKeep.insert(b);
} else if (toErase.count({a,b})) {
toErase.erase({a,b});
} else {
toInsert.insert({a,b});
}
}
vector<change> moves;
oneEdgesKeep.insert(1);
oneEdgesExist.insert(1);
createOneEdges(&nodes[0], &nodes[0], 1, oneEdgesExist, moves);
for (auto e : toInsert) {
node::insert(&nodes[e.first-1], &nodes[e.second-1]);
moves.push_back({e, false});
}
for (auto e : toErase) {
node::erase(&nodes[e.first-1], &nodes[e.second-1]);
moves.push_back({e, true});
}
for (int i = 1; i < n; i++) {
if (!oneEdgesKeep.count(i+1)) {
node::erase(&nodes[0], &nodes[i]);
}
}
eraseOneEdges(&nodes[0], &nodes[0], 2, oneEdgesKeep, moves);
printf("%lld\n", moves.size());
for (auto& m : moves) {
printf("%c %d %d\n", m.remove ? '-' : '+', m.edge.first, m.edge.second);
}
}
void createOneEdges(node* one, node* root, int visited, set<int>& existing, vector<change>& moves) {
if (root->visited == visited) return;
root->visited = visited;
if (existing.count(root->id) == 0) {
node::insert(one, root);
moves.push_back({{1, root->id}, false});
}
for (auto ngh : root->neigh) {
createOneEdges(one, ngh, visited, existing, moves);
}
}
void eraseOneEdges(node* one, node* root, int visited, set<int>& toKeep, vector<change>& moves) {
if (root->visited == visited) return;
root->visited = visited;
for (auto ngh : root->neigh) {
eraseOneEdges(one, ngh, visited, toKeep, moves);
}
if (toKeep.count(root->id) == 0) {
moves.push_back({{1, root->id}, true});
}
}
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 | #include <bits/stdc++.h> using namespace std; struct node { int id = 0; set<node*> neigh = {}; int visited = 0; static void insert(node* a, node* b) { a->neigh.insert(b); b->neigh.insert(a); } static void erase(node* a, node* b) { a->neigh.erase(b); b->neigh.erase(a); } }; typedef pair<node*, node*> edge; struct change { pair<int, int> edge; bool remove; }; void createOneEdges(node* one, node* root, int visited, set<int>& existing, vector<change>& moves); void eraseOneEdges(node* one, node* root, int visited, set<int>& toKeep, vector<change>& moves); int main() { int n; scanf(" %d", &n); vector<node> nodes(n); for (int i = 0; i < n; i++) { nodes[i].id = i+1; } set<pair<int, int>> toInsert; set<pair<int, int>> toErase; set<int> oneEdgesKeep; set<int> oneEdgesExist; int e; scanf(" %d", &e); for (int i = 0; i < e; i++) { int a, b; scanf(" %d %d", &a, &b); if (a > b) swap(a,b); node::insert(&nodes[a-1],&nodes[b-1]); if (a == 1) { oneEdgesExist.insert(b); } else { toErase.insert({a,b}); } } scanf(" %d", &e); for (int i = 0; i < e; i++) { int a, b; scanf(" %d %d", &a, &b); if (a > b) swap(a,b); if (a == 1) { oneEdgesKeep.insert(b); } else if (toErase.count({a,b})) { toErase.erase({a,b}); } else { toInsert.insert({a,b}); } } vector<change> moves; oneEdgesKeep.insert(1); oneEdgesExist.insert(1); createOneEdges(&nodes[0], &nodes[0], 1, oneEdgesExist, moves); for (auto e : toInsert) { node::insert(&nodes[e.first-1], &nodes[e.second-1]); moves.push_back({e, false}); } for (auto e : toErase) { node::erase(&nodes[e.first-1], &nodes[e.second-1]); moves.push_back({e, true}); } for (int i = 1; i < n; i++) { if (!oneEdgesKeep.count(i+1)) { node::erase(&nodes[0], &nodes[i]); } } eraseOneEdges(&nodes[0], &nodes[0], 2, oneEdgesKeep, moves); printf("%lld\n", moves.size()); for (auto& m : moves) { printf("%c %d %d\n", m.remove ? '-' : '+', m.edge.first, m.edge.second); } } void createOneEdges(node* one, node* root, int visited, set<int>& existing, vector<change>& moves) { if (root->visited == visited) return; root->visited = visited; if (existing.count(root->id) == 0) { node::insert(one, root); moves.push_back({{1, root->id}, false}); } for (auto ngh : root->neigh) { createOneEdges(one, ngh, visited, existing, moves); } } void eraseOneEdges(node* one, node* root, int visited, set<int>& toKeep, vector<change>& moves) { if (root->visited == visited) return; root->visited = visited; for (auto ngh : root->neigh) { eraseOneEdges(one, ngh, visited, toKeep, moves); } if (toKeep.count(root->id) == 0) { moves.push_back({{1, root->id}, true}); } } |
English