#include <bits/stdc++.h>
using namespace std;
struct DSU {
vector<int> link;
DSU(int n) {
link.resize(n);
iota(link.begin(), link.end(), 0);
}
int find(int x) {
queue<int> q;
while (x != link[x]) {
q.push(x);
x = link[x];
}
while (!q.empty()) {
link[q.front()] = x;
q.pop();
}
return x;
}
bool same(int u, int v) {
return find(u) == find(v);
}
void unite(int u, int v) {
u = find(u);
v = find(v);
link[v] = u;
}
};
set<int> unvisited;
vector<set<int>> blocked;
vector<pair<int, int>> edges;
void dfs(int cur, int p) {
auto it = unvisited.begin();
vector<int> temp;
while (it != unvisited.end()) {
int e = *it;
if (blocked[cur].find(e) == blocked[cur].end()) {
edges.push_back({e, cur});
temp.push_back(e);
it = unvisited.erase(it);
}
else ++it;
}
for (auto e : temp) dfs(e, cur);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(NULL);
int n, m, k;
cin >> n >> m >> k;
vector<pair<int, int>> init_edges;
bool poss = true;
DSU d(n);
vector<int> outdeg(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
if (d.same(v, u) || outdeg[u]) poss = false;
else {
d.unite(v, u);
init_edges.push_back({u, v});
outdeg[u]++;
}
}
blocked.resize(n);
for (int i = 0; i < k; i++) {
int u, v;
cin >> u >> v;
blocked[v].insert(u);
}
if (!poss) {
cout << "NO\n";
return 0;
}
for (int i = 0; i < n; i++) {
if (d.find(i) == i) unvisited.insert(i);
}
int last = -1;
while (!unvisited.empty()) {
int cur = *unvisited.begin();
unvisited.erase(cur);
last = cur;
dfs(cur, cur);
}
for (int i = 0; i < n; i++) {
if (d.find(i) == i) unvisited.insert(i);
}
edges.clear();
unvisited.erase(last);
dfs(last, last);
if (edges.size()+m != n-1) {
cout << "NO\n";
return 0;
}
for (auto [u, v] : init_edges) cout << u << ' ' << v << '\n';
for (auto [u, v] : edges) cout << u << ' ' << v << '\n';
return 0;
}