#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using PII = pair<ll,ll>;
#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio;

set<PII> st;
vector<PII> ans;
struct twoEdgeComponents {
    int n;
    vector<vector<int>> g;
    vector<int> cmp;
    vector<vector<int>> each_bcc;
    vector<pair<int,int>> bridge;
    vector<int> order;
    vector<bool> inS;
    stack<int> roots, S;

    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.push_back({prev, cur});
            vector<int> bcc;
            while(1) {
                int node = S.top(); S.pop(); inS[node] = false;
                bcc.push_back(node);
                if(node == cur) break;
            }
            each_bcc.push_back(bcc);
            roots.pop();
        }
    }

    twoEdgeComponents() {}
    twoEdgeComponents(int n): n(n), g(n) {}

    void add_edge(int p, int q) {
        g[p].push_back(q);
        g[q].push_back(p);
    }
    void bcc() {
        order.assign(n, 0);
        inS.assign(n, false);
        cmp.assign(n, -1);
        int k = 0;
        for(int i=0; i<n; ++i) {
            if(order[i] == 0) {
                dfs(i, -1, k);
            }
        }
        REP(i, (int)each_bcc.size()) {
            for(auto j: each_bcc[i]) cmp[j] = i;
        }
    }
    using P = pair<ll,PII>;
    vector<vector<P>> getbcc() {
        vector<vector<P>> h(each_bcc.size());
        for(auto i: bridge) {
            int a = cmp[i.first], b = cmp[i.second];
            h[a].push_back({b, i});
            h[b].push_back({a, {i.second, i.first}});
        }
        return h;
    }

    vector<ll> dep;
    void func(ll v, ll p) {
        // cerr << "v=" << v << endl;
        for(auto to: g[v]) {
            if(cmp[v] != cmp[to]) continue;
            if(to == p) continue;
            // cerr << v << " " << to << endl;
            if(dep[to] == -1) {
                ans.push_back({v, to});
                st.insert({min(v, (ll)to), max(v, (ll)to)});
                dep[to] = dep[v] + 1;
                func(to, v);
            }
        }
    }
};

struct LCA {
    const int n = 0;
    const int log2_n = 0;
    vector<vector<int>> g;
    vector<vector<int>> par;  // par[2^i上][頂点v]
    vector<int> dep;

    void dfs(int v, int p, int d) {
        par[0][v] = p;
        dep[v] = d;
        for(auto to: g[v]) {
            if(to == p) continue;
            dfs(to, v, d+1);
        }
    }

    LCA() {}
    LCA(int n) : n(n), log2_n(log2(n)+1), g(n),
        par(log2_n, vector<int>(n)), dep(n) {}

    void add_edge(int u, int v) {
        g[u].push_back(v);
        g[v].push_back(u);
    }

    void build(ll root=0) {
        dfs(root, -1, 0);
        for(int i=0; i+1 < log2_n; ++i) {
            for(int j = 0; j < n; ++j) {
                if(par[i][j] < 0) par[i+1][j] = -1;
                else par[i+1][j] = par[i][par[i][j]];
            }
        }
    }

    int get(int u, int v) {
        if(dep[u] > dep[v]) swap(u, v);
        REP(i, log2_n) {
            if((dep[v] - dep[u]) >> i & 1) {
                v = par[i][v];
            }
        }
        if(u == v) return u;
        for(int i=log2_n-1; i>=0; --i) {
            if(par[i][u] != par[i][v]) {
                u = par[i][u];
                v = par[i][v];
            }
        }
        return par[0][u];
    }
};

signed main() {
    ll n, m;
    cin >> n >> m;
    twoEdgeComponents graph(n);
    vector<ll> a(m), b(m);
    REP(i, m) {
        cin >> a[i] >> b[i];
        a[i]--, b[i]--;
        graph.add_edge(a[i], b[i]);
    }
    graph.bcc();
    // for(auto i: graph.cmp) cerr << i << " ";
    // cerr << endl;

    // サイクルの部分
    graph.dep.assign(n, -1);
    REP(i, graph.each_bcc.size()) {
        // cerr << "i=" << i << endl;
        graph.dep[graph.each_bcc[i][0]] = 0;
        graph.func(graph.each_bcc[i][0], -1);
    }
    REP(i, m) {
        PII p({min(a[i], b[i]), max(a[i], b[i])});
        if(graph.cmp[a[i]] == graph.cmp[b[i]] && st.find(p) == st.end()) {
            if(graph.dep[a[i]] < graph.dep[b[i]]) {
                ans.push_back({b[i], a[i]});
            } else {
                ans.push_back({a[i], b[i]});
            }
            st.insert(p);
        }
    }

    // for(auto p: ans) cout << p.first << "," << p.second << endl;

    auto g = graph.getbcc();
    LCA tree(graph.each_bcc.size());
    REP(i, g.size()) {
        // cout << "i:" << i << " ";
        for(auto j: g[i]) {
            if(i < j.first) tree.add_edge(i, j.first);
            // cout << j.first << "," << j.second.first << "," << j.second.second << " ";
        }
        // cout << endl;
    }
    tree.build();

    vector<ll> up(g.size()), down(g.size());
    ll q;
    cin >> q;
    vector<ll> u(q), v(q);
    REP(i, q) {
        cin >> u[i] >> v[i];
        u[i]--, v[i]--;

        if(graph.cmp[u[i]] == graph.cmp[v[i]]) continue;
        u[i] = graph.cmp[u[i]];
        v[i] = graph.cmp[v[i]];
        ll lca = tree.get(u[i], v[i]);
        // cout << "u=" << u[i] << " v=" << v[i] << " lca=" << lca << endl;
        up[u[i]]++;
        up[lca]--;
        down[v[i]]++;
        down[lca]--;
    }

    // cout << "up:";
    // for(auto i: up) cout << i << " "; 
    // cout << endl << "down:";
    // for(auto i: down) cout << i << " "; 
    // cout << endl;

    function<void(ll,ll)> dfs = [&](ll v, ll p) {
        for(auto to: g[v]) {
            if(to.first == p) continue;
            dfs(to.first, v);

            down[v] += down[to.first];
            up[v] += up[to.first];
            // cerr << v << " " << to.first << " " << down[v] << " " << up[v] << endl;
            if(down[to.first] > 0 && up[to.first] > 0) {
                cout << "No" << endl;
                exit(0);
            } else if(down[to.first] > 0) {
                ans.push_back({to.second.first, to.second.second});
            } else {
                ans.push_back({to.second.second, to.second.first});
            }
        }
    };
    dfs(0, -1);

    cout << "Yes" << endl;
    for(auto p: ans) cout << p.first+1 << " " << p.second+1 << endl;

    // vector<ll> depth(graph.bridge.size()+1);
    // function<void(ll,ll,ll)> pre = [&](ll v, ll p, ll d) {
    //     depth[v] = d;
    //     for(auto to: g[v]) {
    //         if(to.first == p) continue;
    //         pre(to.first, v, d+1);
    //     }
    // };
    // pre(0, -1, 0);

    // ll q;
    // cin >> q;
    // vector<PII> path;
    // vector<set<ll>> up(graph.each_bcc.size()), down(graph.each_bcc.size());
    // while(q--) {
    //     ll u, v;
    //     cin >> u >> v;
    //     u--, v--;
    //     if(graph.cmp[u] != graph.cmp[v]) {
    //         path.push_back({graph.cmp[u], graph.cmp[v]});
    //         if(depth[graph.cmp[u]] > depth[graph.cmp[v]]) {
    //             up[graph.cmp[u]].insert(graph.cmp[v]);
    //         } else {
    //             down[graph.cmp[u]].insert(graph.cmp[v]);
    //         }
    //     }
    // }

    // function<set<ll>(ll,ll,set<ll>&)> dfs = [&](ll v, ll p, set<ll>& st1) {
    //     // st1 と down[v] をmerge
    //     for(auto i: down[v]) st1.insert(i);
    //     // st1 からvを削除
    //     st1.erase(v);
    //     set<ll> ret;
    //     for(auto to: g[v]) {
    //         if(to.first == p) continue;
    //         // 部分木to.first に含まれる頂点がst1に含まれる → 下向きの辺
    //         auto tmp = dfs(to, v, st1);
    //         if(ret.size() < tmp.size()) swap(ret, tmp);
    //         for(auto i: tmp) ret.insert(i);
    //     }
    //     return ret;
    // };

    return 0;
}


Measured memory_bytes: 14480