#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<vector<int>> UnWeightedGraph;
typedef pair<int, int> P;
typedef pair<int, int> i_i;
template <typename T>
bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template <typename T>
bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

struct BECC {
        int N;
        vector<vector<int>> G;
        vector<int> order, inS;
        stack<int> S, roots;
        vector<int> cmp;
        vector<P> bridge;
        vector<vector<int>> bccs;
        vector<vector<int>> dcmp;// composed graph
        BECC(int n, vector<vector<int>> graph) {
            N = n;
            G = graph;
            order = inS = cmp = vector<int>(N + 1, 0);
        }
        void dfs(int cur, int prev, int k) {
            order[cur] = ++k;
            S.push(cur); inS[cur] = true;
            roots.push(cur);
            for(auto to:G[cur]){
                if(order[to]==0) dfs(to,cur,k);
                else if(to!=prev && inS[to]){
                    while(order[roots.top()]>order[to]) roots.pop();
                }
            }
            if(cur==roots.top()){
                if(prev!=-1) bridge.emplace_back(prev,cur);
                vector<int> bcc;
                while(true){
                    int node = S.top(); S.pop(); inS[node] = false;
//                    cerr << node << " " << bcc.size() << endl;
                    bcc.emplace_back(node);
                    cmp[node] = bccs.size()+1;
                    if(node==cur) break;
                }
                bccs.emplace_back(bcc);
                roots.pop();
            }
        }
        int find(int n){return cmp[n];}
        int cmp_size(int n){return bccs[cmp[n]].size();}
        void decomposition(){
            int k = 0;
            for(int i=1;i<=N;i++) if(order[i]==0) dfs(i,-1,k);
            dcmp = vector<vector<int>>(bccs.size()+1);
            for(auto& x:bridge){
                dcmp[cmp[x.first]].push_back(cmp[x.second]);
                dcmp[cmp[x.second]].push_back(cmp[x.first]);
            }
        }
    };


int x[100050], y[100050];
int K;
int a[100500], b[100500];
int N, M;
vector<int> nodes[100500];
vector<int> paths[100500];
vector<int> Rest[100050];
vector<i_i> ans;
bool searched[100050];
set<i_i> UsedEdges;
map<i_i, i_i> Restore;

void dfs1(int from) {
    searched[from] = true;
    for(auto to : paths[from]) {
        if(UsedEdges.find(make_pair(from, to)) != UsedEdges.end()) continue;
        UsedEdges.insert({from, to});
        UsedEdges.insert({to, from});
        ans.push_back({from, to});
        if(!searched[to]) dfs1(to);
    }
}

int main() {
    cin.tie(nullptr); ios::sync_with_stdio(false);
    cin >> N >> M;
    vector<vector<int>> g(N + 1);
    for(int i = 1; i <= M; i++) {
        cin >> x[i] >> y[i];
        g[x[i]].push_back(y[i]);
        g[y[i]].push_back(x[i]);
    }
    cin >> K;
    for(int i = 1; i <= K; i++) {
        cin >> a[i] >> b[i];
    }
    BECC becc(N, g);
    becc.decomposition();
    for(int i = 1; i <= N; i++) {
        nodes[becc.cmp[i]].push_back(i);
    }
    for(int i = 1; i <= M; i++) {
        if(becc.find(x[i]) == becc.find(y[i])) {
            paths[x[i]].push_back(y[i]);
            paths[y[i]].push_back(x[i]);
        } else {
            Rest[x[i]].push_back(y[i]);
            Rest[y[i]].push_back(x[i]);
            Restore[{becc.cmp[x[i]], becc.cmp[y[i]]}] = make_pair(x[i], y[i]);
            Restore[{becc.cmp[y[i]], becc.cmp[x[i]]}] = make_pair(y[i], x[i]);
        }
    }
    for(int i = 1; i <= N; i++) {
        if(nodes[i].empty()) continue;
        dfs1(nodes[i][0]);
    }

//    risujiroh
    {
        auto g = becc.dcmp;
        int n = g.size() - 1;
        {
            vector<int> sz(g.size());
            auto dfs = [&](auto &F, int v, int p) -> void {
                sz[v] = 1;
                for (int u : g[v])
                    if (u != p) {
                        F(F, u, v);
                        sz[v] += sz[u];
                    }
                sort(begin(g[v]), end(g[v]), [&](int l, int r) {
                    return (l != p ? sz[l] : 0) > (r != p ? sz[r] : 0);
                });
            };
            dfs(dfs, 1, -1);
        }
        vector<int> in(g.size()), par(g.size()), anc(g.size()), vs;
        {
            int t = 0;
            auto dfs = [&](auto &F, int v, int p) -> void {
                in[v] = t++;
                vs.push_back(v);
                for (int u : g[v])
                    if (u != p) {
                        par[u] = v;
                        anc[u] = u == g[v][0] ? anc[v] : u;
                        F(F, u, v);
                    }
            };
            dfs(dfs, 1, -1);
        }
        auto lca = [&](int u, int v) -> int {
            while (true) {
                if (in[u] > in[v]) swap(u, v);
                if (anc[u] == anc[v]) return u;
                v = par[anc[v]];
            }
        };
        vector<ll> imos(g.size() + 1);
        auto add = [&](int u, int v, ll x) -> void {
            while (true) {
                if (in[u] > in[v]) swap(u, v);
                if (anc[u] == anc[v]) {
                    imos[in[u] + 1] += x;
                    imos[in[v] + 1] -= x;
                    return;
                }
                imos[in[anc[v]]] += x;
                imos[in[v] + 1] -= x;
                v = par[anc[v]];
            }
        };
        for (int i = 1; i <= K; ++i) {
            if (becc.cmp[a[i]] == becc.cmp[b[i]]) continue;
            int u = becc.cmp[a[i]], v = becc.cmp[b[i]];
            int w = lca(u, v);
            add(u, w, 1);
            add(v, w, 1LL << 30);
        }
        for (int i = 0; i < (int) imos.size() - 1; ++i) {
            imos[i + 1] += imos[i];
        }
        for (ll e : imos) {
            int upper = e >> 30;
            int lower = e & ~(~0ULL << 30);
            if (upper and lower) {
                return cout << "No\n", 0;
            }
        }
        cout << "Yes\n";
        for (int i = 0; i < (int)imos.size() - 1; ++i) {
            int upper = imos[i] >> 30;
            int lower = imos[i] & ~(~0ULL << 30);
            int v = vs[i];
//            if (v == 0) continue;
//            par[v];
            if (lower) {
                 ans.push_back(Restore[make_pair(v, par[v])]);
            } else {
                ans.push_back(Restore[{par[v], v}]);
            }
        }
    }
    for(auto val : ans) {
        if (val.first == 0 or val.second == 0) continue;

        cout<< val.first << " " <<val.second << endl;
    }
    return 0;
}


Measured memory_bytes: 24332