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
// Daniel Grzegorzewski
// while (clock()<=69*CLOCKS_PER_SEC)
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")

#define MP make_pair
#define PB push_back
#define ST first
#define ND second

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

//X.find_by_order(k); - zwraca iterator na k-ty element (numeracja od zerowego)
//X.order_of_key(k); - zwraca liczbę elementów ostro mniejszych niż k

typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<PII> VII;
typedef long long LL;

void init_ios() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
}

const uint64_t SEED = chrono::steady_clock::now().time_since_epoch().count();
mt19937_64 rng(SEED);

const int N = 3*(int)1e4 + 3;

int n, m[2];
VI child[2][N];
set<PII> edg[2];
bool vis[N];

VII gen(int id) {
  VII res;
  set<PII> kr;
  for (int i = 1; i <= n; ++i) {
    vis[i] = false;
    for (int dz: child[id][i])
      kr.insert({i, dz});
  }
  queue<int> q;
  q.push(1);
  vis[1] = true;
  while (!q.empty()) {
    int el = q.front();
    q.pop();
    for (int dz: child[id][el]) {
      if (vis[dz])
        continue;
      vis[dz] = true;
      if (kr.find({1, dz}) == kr.end())
        res.PB({1, dz});
      q.push(dz);
    }
  }
  return res;
}

int main() {
  init_ios();
  cin >> n;
  set<PII> added;
  for (int i = 0; i < 2; ++i) {
    cin >> m[i];
    for (int j = 0; j < m[i]; ++j) {
      int x, y;
      cin >> x >> y;
      if (i == 0)
        added.insert({x, y});
      child[i][x].PB(y);
      child[i][y].PB(x);
      edg[i].insert({x, y});
      edg[i].insert({y, x});
    }
  }
  VII add = gen(0);
  VII diff[2];
  for (const PII& el: edg[1])
    if (edg[0].find(el) == edg[0].end())
      diff[0].PB(el);
  for (const PII& el: edg[0])
    if (edg[1].find(el) == edg[1].end())
      diff[1].PB(el);
  VII rem = gen(1);

  vector<pair<char, PII>> out;
  for (auto& el: add) {
    out.PB({'+', el});
    added.insert(el);
  }
  for (const auto& el: diff[0])
    if (added.find(el) == added.end() && added.find({el.ND, el.ST}) == added.end()) {
    out.PB({'+', el});
    added.insert(el);
  }
  for (const auto& el: diff[1])
    if (el.ST != 1 && el.ND != 1 && (added.find(el) != added.end() || added.find({el.ND, el.ST}) != added.end())) {
    out.PB({'-', el});
    added.erase(el);
    added.erase({el.ND, el.ST});
  }
  while (rem.size() > 0) {
    PII el = rem.back();
    rem.pop_back();
    if (added.find(el) != added.end() || added.find({el.ND, el.ST}) != added.end()) {
      out.PB({'-', el});
      added.erase(el);
      added.erase({el.ND, el.ST});
    }
  }
  cout<<out.size()<<"\n";
  for (const auto& el: out)
    cout<<el.ST<<" "<<el.ND.ST<<" "<<el.ND.ND<<"\n";
}