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
#include <iostream>
#include <algorithm>
#include <vector>
#include <tuple>
#include <utility>

int n;
int ms, md;
std::vector<std::vector<int>> graph;
std::vector<std::vector<int>> wanted;
std::vector<std::pair<int,int>> edges_s;
std::vector<std::pair<int,int>> edges_d;
std::vector<std::tuple<char,int,int>> ops;
std::vector<int> toposort;
std::vector<bool> visited;

bool is_edge_s(int a, int b) {
	return std::binary_search(edges_s.begin(), edges_s.end(), std::pair<int,int>{a, b});
}

bool is_edge_d(int a, int b) {
	return std::binary_search(edges_d.begin(), edges_d.end(), std::pair<int,int>{a, b});
}

void dfs_topo(int x, const std::vector<std::vector<int>> &G) {
	visited[x] = true;
	for (int y : G[x]) {
		if (visited[y]) continue;
		dfs_topo(y, G);
	}
	toposort.push_back(x);
}

int main() {
	std::ios_base::sync_with_stdio(0); std::cin.tie(0); std::cout.tie(0);
	std::cin >> n;
	graph.assign(n, {});
	std::cin >> ms;
	edges_s.resize(ms);
	for (int i = 0; i < ms; ++i) {
		int a, b;
		std::cin >> a >> b;
		--a; --b;
		if (a > b) std::swap(a, b);
		edges_s[i] = {a, b};
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	std::sort(edges_s.begin(), edges_s.end());
	toposort.clear();
	visited.assign(n, false);
	dfs_topo(0, graph);
	std::reverse(toposort.begin(), toposort.end());
//	std::cout << "toposort:";
//	for (int v : toposort) std::cout << ' ' << v;
//	std::cout << '\n';
	for (int i = 1; i < n; ++i) {
		int v = toposort[i];
		if (is_edge_s(0, v)) continue;
		ops.emplace_back('+', 0, v);
		graph[0].push_back(v);
		graph[v].push_back(0);
	}
	std::cin >> md;
	edges_d.reserve(md);
	wanted.assign(n, {});
	for (int i = 0; i < md; ++i) {
		int a, b;
		std::cin >> a >> b;
		--a; --b;
		if (a > b) std::swap(a, b);
		wanted[a].push_back(b);
		wanted[b].push_back(a);
		edges_d.emplace_back(a, b);
		if (a == 0 || is_edge_s(a, b)) continue;
		ops.emplace_back('+', a, b);
	}
	std::sort(edges_d.begin(), edges_d.end());
	toposort.clear();
	visited.assign(n, false);
	dfs_topo(0, wanted);
//	std::cout << "toposort:";
//	for (int v : toposort) std::cout << ' ' << v;
//	std::cout << '\n';
	visited.assign(n, false);
	for (int i = 0; i < n-1; ++i) {
		int v = toposort[i];
		visited[v] = true;
		for (int y : graph[v]) {
			if (visited[y] || y == 0) continue;
			int a = v;
			int b = y;
			if (a > b) std::swap(a, b);
			if (!is_edge_d(a, b)) {
				ops.emplace_back('-', a, b);
			}
		}
		if (!is_edge_d(0, v)) {
			ops.emplace_back('-', 0, v);
		}
	}
	
	std::cout << ops.size() << '\n';
	for (auto [op, a, b] : ops) {
		std::cout << op << ' ' << a+1 << ' ' << b+1 << '\n';
	}
}