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
#include <bits/stdc++.h>
using namespace std;
#define rep(a, b) for (int a = 0; a < (b); a++)
#define rep1(a, b) for (int a = 1; a <= (b); a++)
#define all(x) (x).begin(), (x).end()
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
const int MOD = 1e9 + 7;

#define LOCAL false

const int MAX_V = 3e4 + 7;
const int MAX_E = 5e4 + 7;
int V, E1, E2;

set<pii> edges1, edges2;
vector<int> graph[MAX_V];

vector<pair<int, pii>> ans;

void add(int v1, int v2) {
    if (v1 > v2) swap(v1, v2);
    ans.push_back({1, {v1, v2}});
    
    // debug
    // if (edges1.count({v1, v2})) {
    //     cout << "XD\n";
    //     return;
    // }
    // bool ok = false;
    // rep1(vmid, V) if (vmid != v1 && vmid != v2)
    //     ok |= (edges1.count({min(v1, vmid), max(v1, vmid)}) && edges1.count({min(v2, vmid), max(v2, vmid)}));
    // if (!ok) {
    //     cout << "XD\n";
    //     return;
    // }
    // -----

    edges1.insert({v1, v2});
    graph[v1].push_back(v2);
    graph[v2].push_back(v1);
}
void remove(int v1, int v2) {
    if (v1 > v2) swap(v1, v2);
    ans.push_back({2, {v1, v2}});

    // debug
    // cnt++;
    // if (!edges1.count({v1, v2})) {
    //     cout << "XD1\n";
    //     return;
    // }
    // bool ok = false;
    // rep1(vmid, V) if (vmid != v1 && vmid != v2)
    //     ok |= (edges1.count({min(v1, vmid), max(v1, vmid)}) && edges1.count({min(v2, vmid), max(v2, vmid)}));
    // if (!ok) {
    //     cout << "XD2\n";
    //     return;
    // }
    // -----

    edges1.erase({v1, v2});
}

bool vis[MAX_V];
void dfs(int v) {
    // cout << "dfs(" << v << ")\n";
    vis[v] = true;
    vector<int> toadd;
    if (!edges1.count({1, v}) && v != 1) toadd.push_back(v);
    for (int v: toadd) add(1, v);
    vector<int> togo;
    for (int to: graph[v]) if (!vis[to]) togo.push_back(to); 
    for (int to: togo) dfs(to);
}
bool vis2[MAX_V];
void dfs2(int v, bool root = true) {
    // cout << "dfs2(" << v << ' ' << root << ")\n";
    vis2[v] = true;
    for (int to: graph[v]) if (!vis2[to] && edges1.count({min(v, to), max(v, to)})) dfs2(to, false);
    if (!root && !edges2.count({1, v})) remove(1, v);
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    if (LOCAL) {
        ignore=freopen("io/in", "r", stdin);
        ignore=freopen("io/out", "w", stdout);
    }

    cin >> V;
    cin >> E1;
    int v1, v2;
    rep(i, E1) {
        cin >> v1 >> v2;
        if (v1 > v2) swap(v1, v2);
        edges1.insert({v1, v2});
        graph[v1].push_back(v2);
        graph[v2].push_back(v1);        
    }
    cin >> E2;
    rep(i, E2) {
        cin >> v1 >> v2;
        if (v1 > v2) swap(v1, v2);
        edges2.insert({v1, v2});
    }

    dfs(1);
    for (pii e: edges2) if (!edges1.count(e)) add(e.first, e.second);
    set<pii> edges1cpy = edges1;
    for (pii e: edges1cpy) if (e.first != 1 && !edges2.count(e)) remove(e.first, e.second);
    vis2[1] = true;
    edges1cpy = edges1;
    for (auto [v1, v2]: edges1cpy) if (v1 == 1 && !vis2[v2] && edges2.count({1, v2})) dfs2(v2);

    // if (edges1 == edges2) cout << "GIT\n";

    cout << ans.size() << '\n';
    for (auto [mode, p]: ans) cout << (mode == 1 ? "+ " : "- ") << p.first << ' ' << p.second << '\n';

    return 0;
}