Problem:
One-Way Conveyors
You are working at a factory manufacturing many different products. Products have to be processed on a number of different machine tools. Machine shops with these machines are connected with conveyor lines to exchange unfinished products. Each unfinished product is transferred from a machine shop to another through one or more of these conveyors.
As the orders of the processes required are not the same for different types of products, the conveyor lines are currently operated in two-way. This may induce inefficiency as conveyors have to be completely emptied before switching their directions.
Kaizen
(efficiency improvements) may be found here!
Adding more conveyors is too costly. If all the required transfers are possible with currently installed conveyors operating in fixed directions, no additional costs are required. All the required transfers, from which machine shop to which, are listed at hand. You want to know whether all the required transfers can be enabled with all the conveyors operated in one-way, and if yes, directions of the conveyor lines enabling it.
Input
The input consists of a single test case of the following format.
$n$ $m$
$x_1$ $y_1$
.
.
.
$x_m$ $y_m$
$k$
$a_1$ $b_1$
.
.
.
$a_k$ $b_k$
The first line contains two integers $n$ ($2 \leq n \leq 10 000$) and $m$ ($1 \leq m \leq 100 000$), the number of machine shops and the number of conveyors, respectively. Machine shops are numbered $1$ through $n$. Each of the following $m$ lines contains two integers $x_i$ and $y_i$ ($1 \leq x_i < y_i \leq n$), meaning that the $i$-th conveyor connects machine shops $x_i$ and $y_i$. At most one conveyor is installed between any two machine shops. It is guaranteed that any two machine shops are connected through one or more conveyors. The next line contains an integer $k$ ($1 \leq k \leq 100 000$), which indicates the number of required transfers from a machine shop to another. Each of the following $k$ lines contains two integers $a_i$ and $b_i$ ($1 \leq a_i \leq n$, $1 \leq b_i \leq n$, $a_i \ne b_i$), meaning that transfer from the machine shop $a_i$ to the machine shop $b_i$ is required. Either $a_i \ne a_j$ or $b_i \ne b_j$ holds for $i \ne j$.
Output
Output “
No
” if it is impossible to enable all the required transfers when all the conveyors are operated in one-way. Otherwise, output “
Yes
” in a line first, followed by $m$ lines each of which describes the directions of the conveyors. All the required transfers should be possible with the conveyor lines operated in these directions. Each direction should be described as a pair of the machine shop numbers separated by a space, with the start shop number on the left and the end shop number on the right. The order of these $m$ lines do not matter as far as all the conveyors are specified without duplicates or omissions. If there are multiple feasible direction assignments, whichever is fine.
Sample Input 1
3 2
1 2
2 3
3
1 2
1 3
2 3
Sample Output 1
Yes
1 2
2 3
Sample Inp
...(truncated)

Submitted solutions:

code_snippet: #include <bits/extc++.h>

using namespace std;

#define all(x) begin(x),end(x)
using ll = long long;
using ull = unsigned long long;

struct TwoEdgeConnectedComponents {
public:
    using Graph = vector<vector<int> >;

    Graph g, tree;
    vector<vector<int> > group;
    vector<int> ord, low, comp;
    vector<pair<int, int> > bridge;

    explicit TwoEdgeConnectedComponents(const Graph &G) : g(G), used(G.size()), ord(G.size()), low(G.size()), comp(G.size(), -1) {
        int k = 0;
        for (int i = 0; i < g.size(); ++i) {
            if (!used[i]) k = dfs1(i, k, -1);
        }
        k = 0;
        for (int i = 0; i < g.size(); ++i) {
            if (comp[i] == -1) dfs2(i, -1, k);
        }
        group.resize(k);
        for (int i = 0; i < g.size(); ++i) {
            group[comp[i]].emplace_back(i);
        }
        tree.resize(k);
        for (auto &e : bridge) {
            tree[comp[e.first]].emplace_back(comp[e.second]);
            tree[comp[e.second]].emplace_back(comp[e.first]);
        }
    }

    explicit TwoEdgeConnectedComponents() = default;

private:
    vector<bool> used;

    int dfs1(int idx, int k, int par) {
        used[idx] = true;
        ord[idx] = k++;
        low[idx] = ord[idx];
        int cnt = 0;
        bool one = true;
        for (auto &to : g[idx]) {
            if (to == par && exchange(one, false)) continue;
            if (!used[to]) {
                ++cnt;
                k = dfs1(to, k, idx);
                low[idx] = min(low[idx], low[to]);
                if (ord[idx] < low[to]) bridge.emplace_back(idx, to);
            } else {
                low[idx] = min(low[idx], ord[to]);
            }
        }
        return (k);
    }

    void dfs2(int idx, int par, int &k) {
        if (par >= 0 && ord[par] >= low[idx]) comp[idx] = comp[par];
        else comp[idx] = k++;
        for (auto &to : g[idx]) {
            if (comp[to] == -1) dfs2(to, idx, k);
        }
    }
};

struct LowestCommonAncestor{
    int n;
    const vector<vector<int> > g;
    vector<vector<int> > table;
    vector<int> depth;
    int logk;

    LowestCommonAncestor(const vector<vector<int> > &G) : g(G){
        n = g.size();
        logk = 32 - __builtin_clz(g.size());
        table.assign(logk, vector<int>(n, -1));
        depth.assign(n, -1);
        build();
    }

    void build(int s = 0, bool isforest = false){
        if(isforest){
            for(int i = 0; i < n; ++i){
                if(depth[i] == -1){
                    dfs(i, -1, 0);
                }
            }
        }else{
            dfs(s, -1, 0);
        }
        for(int k = 0; k < logk - 1; ++k){
            for(int i = 1; i <= n - 1; ++i){
                if(table[k][i] == -1){
                    table[k + 1][i] = -1;
                }else{
                    table[k + 1][i] = table[k][table[k][i]];
                }
            }
        }
    }

    void dfs(int now, int pre, int dep){
        table[0][now] = pre;
        depth[now] = dep;
        for(const auto& to: g[now]){
            if(to != pre){
                dfs(to, now, dep + 1);
            }
        }
    }

    int query(int u, int v){
        if(depth[u] < depth[v]) swap(u, v);
        for(int k = logk - 1; k >= 0; --k){
            if(depth[u] - depth[v] & 1 << k){
                u = table[k][u];
            }
        }
        if(u == v) return (u);
        for(int k = logk - 1; k >= 0; --k){
            if(table[k][u] != table[k][v]){
                u = table[k][u];
                v = table[k][v];
            }
        }
        return (table[0][u]);
    }

    int dist(int u, int v){
        return (depth[u] + depth[v] - 2 * depth[query(u, v)]);
    }
};

int main(){
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout.setf(ios_base::fixed);
    cout.precision(12);

    int n, m;
    cin >> n >> m;

    vector<vector<int> > g(n);

    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        --x, --y;

        g[x].emplace_back(y);
        g[y].emplace_back(x);
    }

    TwoEdgeConnectedComponents tecc(g);
    auto &comp = tecc.comp;
    auto &group = tecc.group;
    auto &tree = tecc.tree;

    vector<unordered_set<int> > g2(n);

    for (int i = 0; i < n; ++i) {
        for (auto to : g[i]) {
            if (comp[i] == comp[to]) {
                g2[i].insert(to);
                g2[to].insert(i);
            }
        }
    }

    vector<vector<int> > g3(n);
    vector<bool> visited(n);

    for (int i = 0; i < n; ++i) {
        auto rec = [&](auto rec, int cur) -> void {
            visited[cur] = true;
            while (!g2[cur].empty()) {
                int to = *g2[cur].begin();
                g2[cur].erase(g2[cur].begin());
                g2[to].erase(cur);
                g3[cur].emplace_back(to);
                if (!visited[to]) {
                    rec(rec, to);
                }
            }
        };
        rec(rec, i);
    }

    LowestCommonAncestor lca(tree);
    int l = tree.size();
    vector<pair<int, int> > dp(l);

    int k;
    cin >> k;

    for (int i = 0; i < k; ++i) {
        int a, b;
        cin >> a >> b;
        --a, --b;
        a = comp[a];
        b = comp[b];
        int c = lca.query(a, b);
        dp[a].first++;
        dp[b].second++;
        dp[c].first--;
        dp[c].second--;
    }

    map<pair<int, int>, pair<int, int> > mp;

    for (auto [u, v] : tecc.bridge) {
        if (comp[u] > comp[v]) swap(u, v);
        mp[pair(comp[u], comp[v])] = pair(u, v);
    }

    auto rec = [&](auto rec, int cur, int pre) -> pair<int, int> {
        for (auto to : tree[cur]) {
            if (to != pre) {
                auto [f, s] = rec(rec, to, cur);
                dp[cur].first += f;
                dp[cur].second += s;
            }
        }
        if (dp[cur].first > 0 && dp[cur].second > 0) {
            cout << "No\n";
            exit(0);
        } else if (dp[cur].first > 0) {
            auto [u, v] = pair(cur, pre);
            if (cur > pre) tie(v, u) = mp[pair(pre, cur)];
            else tie(u, v) = mp[pair(cur, pre)];
            g3[u].emplace_back(v);
        } else if (pre != -1) {
            auto [u, v] = pair(cur, pre);
            if (cur > pre) tie(u, v) = mp[pair(pre, cur)];
            else tie(v, u) = mp[pair(cur, pre)];
            g3[u].emplace_back(v);
        }
        return dp[cur];
    };

    rec(rec, 0, -1);

    cout << "Yes\n";

    for (int i = 0; i < n; ++i) {
        for (auto to : g3[i]) {
            cout << i + 1 << ' ' << to + 1 << '\n';
        }
    }

    return (0);
}
accuracy: 1
time_ms: 60
memory_kb: 14800
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define pll pair<LL,LL>
#define x first
#define y second
#define pi acos(-1)
#define sqr(x) ((x)*(x))
#define pdd pair<double,double>
#define MEMS(x) memset(x,-1,sizeof(x))
#define MEM(x) memset(x,0,sizeof(x))
#define less Less
#define EPS 1e-4
#define arg ARG
#define cpdd const pdd
#define rank Rank
#define KK 500
#define N 100005
#define MXN 2000005
vector<int> v[100005];
int vis[100005],lwn[100005];
vector<int> stk;
int f[100005];
int bln[100005];
int Find(int a){
    if(bln[a]==a)return a;
    return bln[a]=Find(bln[a]);
}
int t;
void dfs(int a,int p){
    stk.pb(a);
    bln[a]=a;
    vis[a]=lwn[a]=++t;
    for(auto x:v[a]){
        if(x!=p){
            if(vis[x]==0){
                dfs(x,a);
                if(lwn[x]>vis[a]){
                    int fa=Find(x);
                    f[x]=Find(a);
                    while(stk.back()!=x){
                        bln[stk.back()]=fa;
                        stk.pop_back();
                    }
                    bln[stk.back()]=fa;
                    stk.pop_back();
                }
                lwn[a]=min(lwn[a],lwn[x]);
            }
            else{
                lwn[a]=min(lwn[a],vis[x]);
            }
        }
    }
}
vector<int> tv[100005];
vector<pii> mystk;
vector<pii> seg[100005];
int in[100005];
int p[100005][20];
int dis[100005];
void dfs2(int x,int f){
    in[x]=++t;
    p[x][0]=f;
    dis[x]=dis[f]+1;
    if(mystk.empty()||mystk.back().y+1!=t){
        mystk.pb(mp(t,t));
    }
    else{
        mystk.back().y++;
    }
    seg[x]=mystk;
    for(auto it:tv[x]){
        if(it!=f){
            dfs2(it,x);
        }
    }
    mystk.back().y--;
    if(mystk.back().y<mystk.back().x)mystk.pop_back();
}
void build(int n){
    for(int i = 1;i<20;i++){
        for(int j=1;j<=n;j++){
            p[j][i]=p[p[j][i-1]][i-1];
        }
    }
}
int lca(int x,int y){
    if(dis[x]>dis[y])swap(x,y);
    int b=dis[y]-dis[x];
    for(int j=0;j<20;j++){
        if(b&(1<<j))y=p[y][j];
    }
    if(x==y)return x;
    for(int i =19;i>=0;i--){
        if(p[x][i]!=p[y][i]){
            x=p[x][i];
            y=p[y][i];
        }
    }
    return p[x][0];
}
struct node{
    node *l,*r;
    int cnt[2];
    int a,b;
    node(int _a,int _b):l(NULL),r(NULL),a(_a),b(_b){
        cnt[0]=cnt[1]=0;
    }
}*root;
void push(node *n){
    for(int i = 0;i<2;i++){
        n->l->cnt[i]+=n->cnt[i];
        n->r->cnt[i]+=n->cnt[i];
        n->cnt[i]=0;
    }
}
void build(node *n){
    if(n->a==n->b)return ;
    int mid=(n->a+n->b)/2;
    n->l=new node(n->a,mid);
    n->r=new node(mid+1,n->b);
    build(n->l);
    build(n->r);
}
void add(node *n,int l,int r,int op,int k){
  //  printf("%d\n",n);
    //printf("%d %d %d %d\n",n->a,n->b,l,r);
    if(n->a>=l&&n->b<=r){
        n->cnt[op]+=k;
        return;
    }
    if(n->b<l||n->a>r)return;
    push(n);
    add(n->l,l,r,op,k);
    add(n->r,l,r,op,k);
}
pii query(node *n,int k){
    if(n->a==n->b)return mp(n->cnt[0],n->cnt[1]);
    int mid=(n->a+n->b)/2;
    push(n);
    if(k<=mid)return query(n->l,k);
    else return query(n->r,k);
}
vector<pii> ans;
void dfs3(int x,int f){
 //   printf("%d\n",x);
    vis[x]=++t;
    for(auto it:v[x]){
        if(Find(it)!=Find(x))continue;
        if(it!=f){
            if(!vis[it]){
                ans.pb(mp(x,it));
                dfs3(it,x);
            }
            else if(vis[it]<vis[x]){
                ans.pb(mp(x,it));
            }
        }    
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    pii p[100005];
    for(int i = 0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        v[x].pb(y);
        v[y].pb(x);
        p[i]=mp(x,y);
    }
    v[0].pb(1);
    v[1].pb(0);
    dfs(0,0);
   // for(int i = 1;i<=n;i++)
  //  printf("%d ",Find(i));
    for(int i = 0;i<m;i++){
        if(Find(p[i].x)!=Find(p[i].y)){
            tv[Find(p[i].x)].pb(Find(p[i].y));
            tv[Find(p[i].y)].pb(Find(p[i].x));
        }
    }
    t=0;
    dfs2(Find(1),0);
    build(n);
    root=new node(1,t);
    build(root);
    int q;
    scanf("%d",&q);
    while(q--){
        int x,y;
        scanf("%d %d",&x,&y);
        if(Find(x)!=Find(y)){
            int a=Find(x),b=Find(y);
            int ca=lca(a,b);
            for(auto it:seg[a]){
         //       printf("!1 %d %d\n",it.x,it.y);
                add(root,it.x,it.y,1,1);
            }
            for(auto it:seg[b]){
                add(root,it.x,it.y,0,1);
             //   printf("!!2 %d %d\n",it.x,it.y);
            }
            for(auto it:seg[ca]){
            //    printf("!!!3 %d %d\n",it.x,it.y);
                add(root,it.x,it.y,0,-1);
                add(root,it.x,it.y,1,-1);
            }
        }
    }
    for(int i = 1;i<=t;i++){
        pii p=query(root,i);
        if(p.x&&p.y){
            printf("No\n");
            return 0;
        }
    }
    printf("Yes\n");
    MEM(vis);
    t=0;
    for(int i = 1;i<=n;i++)
    if(!vis[i])
    dfs3(i,0);
    for(int i = 0;i<m;i++){
        int x=Find(p[i].x);
        int y=Find(p[i].y);
        if(x!=y){
            if(in[x]<in[y]){
                pii pp=query(root,in[y]);
                if(pp.y)swap(p[i].x,p[i].y);
            }
            else{
                pii pp=query(root,in[x]);
                if(pp.x)swap(p[i].x,p[i].y);
            }
          //  printf("?%d %d %d %d\n",p[i].x,p[i].y,x,y);
            ans.pb(p[i]);
        }
    }
    for(auto it:ans)printf("%d %d\n",it.x,it.y);
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 16972
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
#include <functional>
#include <stack>
#include <cstring>
using namespace std;

const int MAXN = 10005;
const int MAXM = 100005;
const int LOG = 15;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int n, m;
    cin >> n >> m;
    vector<pair<int, int>> edges;
    vector<vector<pair<int, int>>> graph(n);

    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        edges.push_back({u, v});
        graph[u].push_back({v, i});
        graph[v].push_back({u, i});
    }

    // Find bridges
    vector<int> tin(n, -1), low(n, -1);
    vector<bool> visited(n, false);
    vector<bool> is_bridge(m, false);
    int timer = 0;

    function<void(int, int)> dfs_bridges = [&](int u, int p) {
        visited[u] = true;
        tin[u] = low[u] = timer++;
        for (auto [v, id] : graph[u]) {
            if (v == p) continue;
            if (visited[v]) {
                low[u] = min(low[u], tin[v]);
            } else {
                dfs_bridges(v, u);
                low[u] = min(low[u], low[v]);
                if (low[v] > tin[u]) {
                    is_bridge[id] = true;
                }
            }
        }
    };

    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            dfs_bridges(i, -1);
        }
    }

    // Assign components (ignore bridges)
    vector<int> comp(n, -1);
    vector<bool> vis(n, false);
    int comp_id = 0;
    for (int i = 0; i < n; i++) {
        if (vis[i]) continue;
        queue<int> q;
        q.push(i);
        vis[i] = true;
        comp[i] = comp_id;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (auto [v, id] : graph[u]) {
                if (vis[v]) continue;
                if (is_bridge[id]) continue;
                vis[v] = true;
                comp[v] = comp_id;
                q.push(v);
            }
        }
        comp_id++;
    }

    // Build block-cut tree
    vector<vector<int>> comp_graph(comp_id);
    for (int id = 0; id < m; id++) {
        if (is_bridge[id]) {
            int u = edges[id].first, v = edges[id].second;
            int c1 = comp[u], c2 = comp[v];
            comp_graph[c1].push_back(c2);
            comp_graph[c2].push_back(c1);
        }
    }

    // Choose root (vertex 0)
    int root_comp = comp[0];
    vector<int> parent_comp(comp_id, -1);
    vector<int> depth_comp(comp_id, -1);
    queue<int> q_tree;
    q_tree.push(root_comp);
    depth_comp[root_comp] = 0;
    parent_comp[root_comp] = -1;
    vector<set<int>> comp_graph_set(comp_id);
    while (!q_tree.empty()) {
        int u_comp = q_tree.front(); q_tree.pop();
        for (int v_comp : comp_graph[u_comp]) {
            if (v_comp == parent_comp[u_comp]) continue;
            parent_comp[v_comp] = u_comp;
            depth_comp[v_comp] = depth_comp[u_comp] + 1;
            comp_graph_set[u_comp].insert(v_comp);
            comp_graph_set[v_comp].insert(u_comp);
            q_tree.push(v_comp);
        }
    }

    // Build LCA
    vector<vector<int>> up(comp_id, vector<int>(LOG, -1));
    for (int i = 0; i < comp_id; i++) {
        up[i][0] = parent_comp[i];
    }
    for (int j = 1; j < LOG; j++) {
        for (int i = 0; i < comp_id; i++) {
            if (up[i][j-1] != -1) {
                up[i][j] = up[up[i][j-1]][j-1];
            } else {
                up[i][j] = -1;
            }
        }
    }

    auto lca = [&](int a, int b) {
        if (depth_comp[a] < depth_comp[b]) swap(a, b);
        int d = depth_comp[a] - depth_comp[b];
        for (int j = 0; j < LOG; j++) {
            if (d & (1 << j)) {
                a = up[a][j];
            }
        }
        if (a == b) return a;
        for (int j = LOG-1; j >= 0; j--) {
            if (up[a][j] != up[b][j]) {
                a = up[a][j];
                b = up[b][j];
            }
        }
        return up[a][0];
    };

    // Process k requirements
    int k;
    cin >> k;
    vector<int> F_up(comp_id, 0), F_down(comp_id, 0);
    for (int i = 0; i < k; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        int c_a = comp[a], c_b = comp[b];
        if (c_a == c_b) continue;
        int l = lca(c_a, c_b);
        F_up[c_a]++;
        if (l != -1) F_up[l]--;
        F_down[c_b]++;
        if (l != -1) F_down[l]--;
    }

    // Build children list
    vector<vector<int>> children(comp_id);
    for (int i = 0; i < comp_id; i++) {
        if (parent_comp[i] != -1) {
            children[parent_comp[i]].push_back(i);
        }
    }

    // DFS for up counts
    vector<int> S_up(comp_id, 0);
    function<void(int)> dfs_up = [&](int u_comp) {
        S_up[u_comp] = F_up[u_comp];
        for (int v_comp : children[u_comp]) {
            dfs_up(v_comp);
            S_up[u_comp] += S_up[v_comp];
        }
    };
    dfs_up(root_comp);

    // DFS for down counts
    vector<int> S_down(comp_id, 0);
    function<void(int)> dfs_down = [&](int u_comp) {
        S_down[u_comp] = F_down[u_comp];
        for (int v_comp : children[u_comp]) {
            dfs_down(v_comp);
            S_down[u_comp] += S_down[v_comp];
        }
    };
    dfs_down(root_comp);

    // Check for conflicts
    for (int i = 0; i < comp_id; i++) {
        if (i != root_comp && S_up[i] > 0 && S_down[i] > 0) {
            cout << "No" << endl;
            return 0;
        }
    }

    // If no conflicts, output "Yes" and orientations
    cout << "Yes" << endl;

    // Orient bridges
    vector<pair<int, int>> directed_edges(m);
    for (int id = 0; id < m; id++) {
        if (is_bridge[id]) {
            int u = edges[id].first, v = edges[id].second;
            int c1 = comp[u], c2 = comp[v];
            int child_comp = -1, parent_comp_val = -1;
            if (parent_comp[c2] == c1) {
                child_comp = c2;
                parent_comp_val = c1;
            } else if (parent_comp[c1] == c2) {
                child_comp = c1;
                parent_comp_val = c2;
            } else {
                if (c1 == root_comp) {
                    child_comp = c2;
                    parent_comp_val = c1;
                } else if (c2 == root_comp) {
                    child_comp = c1;
                    parent_comp_val = c2;
                } else {
                    directed_edges[id] = (u < v) ? make_pair(u, v) : make_pair(v, u);
                    continue;
                }
            }
            if (S_up[child_comp] > 0) {
                if (comp[u] == child_comp) {
                    directed_edges[id] = {u, v};
                } else {
                    directed_edges[id] = {v, u};
                }
            } else if (S_down[child_comp] > 0) {
                if (comp[u] == parent_comp_val) {
                    directed_edges[id] = {u, v};
                } else {
                    directed_edges[id] = {v, u};
                }
            } else {
                directed_edges[id] = (u < v) ? make_pair(u, v) : make_pair(v, u);
            }
        }
    }

    // Orient non-bridge edges
    vector<int> depth_in_comp(n, -1);
    vector<bool> visited_in_comp(n, false);
    for (int i = 0; i < n; i++) {
        if (visited_in_comp[i]) continue;
        queue<int> q_comp;
        vector<int> comp_vertices;
        comp_vertices.push_back(i);
        q_comp.push(i);
        visited_in_comp[i] = true;
        while (!q_comp.empty()) {
            int u = q_comp.front(); q_comp.pop();
            for (auto [v, id] : graph[u]) {
                if (is_bridge[id]) continue;
                if (!visited_in_comp[v]) {
                    visited_in_comp[v] = true;
                    comp_vertices.push_back(v);
                    q_comp.push(v);
                }
            }
        }
        // BFS to set depths
        int root_comp = *min_element(comp_vertices.begin(), comp_vertices.end());
        queue<int> q_depth;
        q_depth.push(root_comp);
        depth_in_comp[root_comp] = 0;
        while (!q_depth.empty()) {
            int u = q_depth.front(); q_depth.pop();
            for (auto [v, id] : graph[u]) {
                if (is_bridge[id]) continue;
                if (depth_in_comp[v] == -1) {
                    depth_in_comp[v] = depth_in_comp[u] + 1;
                    q_depth.push(v);
                }
            }
        }
    }

    for (int id = 0; id < m; id++) {
        if (!is_bridge[id]) {
            int u = edges[id].first, v = edges[id].second;
            if (depth_in_comp[u] < depth_in_comp[v]) {
                directed_edges[id] = {u, v};
            } else {
                directed_edges[id] = {v, u};
            }
        }
    }

    // Output the directed edges
    for (int id = 0; id < m; id++) {
        cout << directed_edges[id].first + 1 << " " << directed_edges[id].second + 1 << endl;
    }

    return 0;
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 6256
final_rank: 16

code_snippet: #include<bits/stdc++.h>
#define rint register int 
#define ll long long
#define pa pair<int,int> 
#define mk make_pair
#define debug(x) cerr<<#x<<"="<<x<<"\n"
using namespace std;
struct node{
	int to,next;
}e[1010100];
struct T{
	node e[1010100];
	int tot,h[1010100];
	inline void add(int from,int to){e[++tot].next=h[from];h[from]=tot;e[tot].to=to;}
}Tree;
int n,m,tot=1,h[1010010];
int DFN[1010000],LOW[1010000],Visit_Num,ps[1010100],bridge[1000001],cnt,bel[1100100];
inline void add(int from,int to) { e[++tot].next=h[from];h[from]=tot;e[tot].to=to;}
inline void Tarjan(int x,int f) {
	DFN[x]=LOW[x]=++Visit_Num;
	for(rint i=h[x];i;i=e[i].next) {
		int to=e[i].to;
		if(!DFN[to]) {
			Tarjan(to,x);
			LOW[x]=min(LOW[x],LOW[to]);
			if(LOW[to]>DFN[x]) {
				bridge[i]=bridge[i^1]=1;
			}
		}
		else if(DFN[to]<DFN[x]&&to!=f){
			LOW[x]=min(LOW[x],DFN[to]);
		}
	}
}
int ans1[1010000],ans2[1010100],tt,vis[1010100],depp[1010100];
void dfs(int x,int f){
	DFN[x]=1;bel[x]=cnt;
	depp[x]=depp[f]+1;
	for(rint i=h[x];i;i=e[i].next) {
		if(e[i].to==f) continue;
		if(bridge[i]) continue;
		else 
		{
			if(!DFN[e[i].to]) ans1[++tt]=x,ans2[tt]=e[i].to,dfs(e[i].to,x);
			else if(depp[e[i].to]<depp[x]) ans1[++tt]=x,ans2[tt]=e[i].to;
		}
	}
}
pa tmp[110100];int num;
map<pa,int> mp;
int fa[101010][20],dep[101000];
inline void Pre_DFS(int now,int ffa){
	fa[now][0]=ffa;
//	debug(now);
	dep[now]=dep[ffa]+1;
	for(rint i=Tree.h[now];i;i=Tree.e[i].next) {
		int to=Tree.e[i].to;
		if(to==ffa) continue;
		Pre_DFS(to,now);
	}
}
inline int LCA(int u,int v) {
	if(u==v) return u;
	if(dep[u]<dep[v]) swap(u,v);
	for(rint i=19;i>=0;--i) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
	if(u==v) return u;
	for(rint i=19;i>=0;--i) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
	return fa[u][0];
}int Sum1[1010000],Sum2[1010010];
inline void Gao(int now,int ffa) {
	for(rint i=Tree.h[now];i;i=Tree.e[i].next) {
		int to=Tree.e[i].to;if(to==ffa) continue;
		Gao(to,now);
		Sum1[now]+=Sum1[to];
		Sum2[now]+=Sum2[to];
		if(Sum1[to]&&Sum2[to]) {
			cout<<"No"<<"\n";
			exit(0);
		}
		if(Sum1[to]) {
			int idx=mp[mk(now,to)];
			int u=e[idx*2].to,v=e[idx*2+1].to;
			if(bel[u]==to) {
				ans1[++tt]=u,ans2[tt]=v;
			} 
			else ans1[++tt]=v,ans2[tt]=u;
		}
		else {
			int idx=mp[mk(now,to)];
			int u=e[idx*2].to,v=e[idx*2+1].to;
			if(bel[u]==to) {
				ans2[++tt]=u,ans1[tt]=v;
			} 
			else ans2[++tt]=v,ans1[tt]=u;
		}
	}
}
inline void Solve() {
	int T;
//	debug(tt);
	scanf("%d",&T);
	for(rint i=1;i<=T;++i) {
		int x,y;
		scanf("%d%d",&x,&y);
		if(bel[x]==bel[y]) continue;
		tmp[++num]=mk(bel[x],bel[y]);
	}
	for(rint i=1;i<=n;++i) {
		for(rint j=h[i];j;j=e[j].next) {
			int to=e[j].to;
			if(i>to) continue;
			if(bel[i]==bel[to]) continue;
			Tree.add(bel[i],bel[to]);
			Tree.add(bel[to],bel[i]);
			mp[mk(bel[i],bel[to])]=mp[mk(bel[to],bel[i])]=j/2;
		}
	}
	Pre_DFS(1,0);
	for(rint i=1;i<=19;++i) {
		for(rint j=1;j<=cnt;++j) {
			fa[j][i]=fa[fa[j][i-1]][i-1];
		}
	}
	for(rint i=1;i<=num;++i) {
		int u=tmp[i].first,v=tmp[i].second;
		int l=LCA(u,v);
		Sum1[u]++;
		Sum1[l]--;
		Sum2[v]++;
		Sum2[l]--;
	}
	Gao(1,0);
	cout<<"Yes\n";
	for(rint i=1;i<=tt;++i) {
		cout<<ans1[i]<<" "<<ans2[i]<<"\n";
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(rint i=1;i<=m;++i) {
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
	}
	Tarjan(1,0);
	memset(DFN,0,sizeof(DFN));
	for(rint i=1;i<=n;++i) {
//		debug(1);
		if(!DFN[i]) ++cnt,dfs(i,0);
	}
//	debug(cnt);
	Solve();
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 38440
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve(){
    int n, m; cin >> n >> m;
    vector g(n, vector<int>());
    for(int i = 0; i < m; i++) {
        int x, y; cin >> x >> y; x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> par(n);
    vector<vector<int>> child(n);
    vector<int> par_is_bridge(n);
    vector<pair<int, int>> ans;
    vector<int> ord(n, -1), low(n, -1);
    int idx = 0;
    auto dfs = [&](auto&& self, int u, int p) -> void {
        ord[u] = idx++;
        low[u] = ord[u];
        for(int v : g[u]) {
            if(v == p) continue;
            if(ord[v] != -1) {
                if(ord[v] < ord[u]) {
                    ans.emplace_back(u, v);
                    if(low[u] > ord[v]) low[u] = ord[v];
                }
            } else {
                child[u].push_back(v);
                par[v] = u;
                self(self, v, u);
                if(low[u] > low[v]) low[u] = low[v];
            }
        }
        if(p == -1) return;
        if(ord[p] < low[u]) par_is_bridge[u] = true;
        else ans.emplace_back(par[u], u);
    };
    dfs(dfs, 0, -1);
    vector<int> group(n, -1);
    group[0] = 0;
    vector<int> groot = {0};
    vector<int> gdepth = {0};
    auto dfs2 = [&](auto&& self, int u, int p) -> void {
        for(int v : child[u]) {
            if(par_is_bridge[v]) {
                group[v] = ssize(groot);
                groot.push_back(v);
                gdepth.push_back(gdepth[group[u]]+1);
            } else {
                group[v] = group[u];
            }
            self(self, v, u);
        }
    };
    dfs2(dfs2, 0, -1);
    int LOG = 16;
    int ng = ssize(groot);
    vector<vector<int>> gpar(LOG+1, vector<int>(ng, -1));
    for(int i = 0; i < ng; i++) {
        gpar[0][i] = i == 0 ? -1 : group[par[groot[i]]];
    }
    for(int l = 0; l < LOG; l++) for(int i = 0; i < ng; i++) {
        if(gpar[l][i] != -1) gpar[l+1][i] = gpar[l][gpar[l][i]];
    }
    auto climb = [&](int gu, int h) {
        for(int l = LOG; l >= 0; l--) {
            if(h >> l & 1) gu = gpar[l][gu];
            assert(gu != -1);
        }
        return gu;
    };
    auto climb_to_lca = [&](auto&& self, int gu, int gv) -> pair<int, int> {
        int du = gdepth[gu], dv = gdepth[gv];
        if(du > dv) {
            auto [cu, cv] = self(self, climb(gu, du-dv), gv);
            return {cu+(du-dv), cv};
        }
        if(du < dv) {
            auto [cu, cv] = self(self, gu, climb(gv, dv-du));
            return {cu, cv+(dv-du)};
        }
        if(gu == gv) return {0, 0};
        int ans = 0;
        for(int l = LOG; l >= 0; l--) {
            if(gpar[l][gu] != gpar[l][gv]) {
                ans += 1<<l;
                gu = gpar[l][gu];
                gv = gpar[l][gv];
            }
        }
        assert(gu != gv && gpar[0][gu] == gpar[0][gv]);
        return {ans+1, ans+1};
    };
    vector<pair<int, int>> state(ng);
    int k; cin >> k;
    for(int q = 0; q < k; q++) {
        int a, b; cin >> a >> b; a--; b--;
        int ga = group[a], gb = group[b];
        auto [ca, cb] = climb_to_lca(climb_to_lca, ga, gb);
        if(state[ga].first < ca) state[ga].first = ca;
        if(state[gb].second < cb) state[gb].second = cb;
    }
    for(int g = ng-1; g >= 0; g--) {
        if(state[g].first > 0 && state[g].second > 0) {
            cout << "No\n";
            return false;
        }
        if(state[g].first > 0) {
            assert(g != 0);
            ans.emplace_back(groot[g], par[groot[g]]);
            if(state[gpar[0][g]].first < state[g].first-1) {
                state[gpar[0][g]].first = state[g].first-1;
            }
        } else if(state[g].second > 0) {
            assert(g != 0);
            ans.emplace_back(par[groot[g]], groot[g]);
            if(state[gpar[0][g]].second < state[g].second-1) {
                state[gpar[0][g]].second = state[g].second-1;
            }
        } else if(g != 0) {
            ans.emplace_back(groot[g], par[groot[g]]);
        }
    }
    cout << "Yes\n";
    for(auto [u, v] : ans) {
        cout << u+1 << ' ' << v+1 << '\n';
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(solve());
}
accuracy: 1
time_ms: 10
memory_kb: 7208
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve(){
    int n, m; cin >> n >> m;
    vector g(n, vector<int>());
    for(int i = 0; i < m; i++) {
        int x, y; cin >> x >> y; x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> par(n);
    vector<vector<int>> child(n);
    vector<int> par_is_bridge(n);
    vector<pair<int, int>> ans;
    vector<int> ord(n, -1), low(n, -1);
    int idx = 0;
    auto dfs = [&](auto&& self, int u, int p) -> void {
        ord[u] = idx++;
        low[u] = ord[u];
        for(int v : g[u]) {
            if(v == p) continue;
            if(ord[v] != -1) {
                if(ord[v] < ord[u]) {
                    ans.emplace_back(u, v);
                    if(low[u] > ord[v]) low[u] = ord[v];
                }
            } else {
                child[u].push_back(v);
                par[v] = u;
                self(self, v, u);
                if(low[u] > low[v]) low[u] = low[v];
            }
        }
        if(p == -1) return;
        if(ord[p] < low[u]) par_is_bridge[u] = true;
        else ans.emplace_back(par[u], u);
    };
    dfs(dfs, 0, -1);
    assert(ssize(ans) + ranges::count(par_is_bridge, true) == m);
    vector<int> group(n, -1);
    group[0] = 0;
    vector<int> groot = {0};
    vector<int> gdepth = {0};
    auto dfs2 = [&](auto&& self, int u, int p) -> void {
        for(int v : child[u]) {
            if(par_is_bridge[v]) {
                group[v] = ssize(groot);
                groot.push_back(v);
                gdepth.push_back(gdepth[group[u]]+1);
            } else {
                group[v] = group[u];
            }
            self(self, v, u);
        }
    };
    dfs2(dfs2, 0, -1);
    int LOG = 16;
    int ng = ssize(groot);
    vector<vector<int>> gpar(LOG+1, vector<int>(ng, -1));
    for(int i = 0; i < ng; i++) {
        gpar[0][i] = i == 0 ? -1 : group[par[groot[i]]];
    }
    for(int l = 0; l < LOG; l++) for(int i = 0; i < ng; i++) {
        if(gpar[l][i] != -1) gpar[l+1][i] = gpar[l][gpar[l][i]];
    }
    auto climb = [&](int gu, int h) {
        for(int l = LOG; l >= 0; l--) {
            if(h >> l & 1) gu = gpar[l][gu];
            assert(gu != -1);
        }
        return gu;
    };
    auto climb_to_lca = [&](auto&& self, int gu, int gv) -> pair<int, int> {
        int du = gdepth[gu], dv = gdepth[gv];
        if(du > dv) {
            auto [cu, cv] = self(self, climb(gu, du-dv), gv);
            return {cu+(du-dv), cv};
        }
        if(du < dv) {
            auto [cu, cv] = self(self, gu, climb(gv, dv-du));
            return {cu, cv+(dv-du)};
        }
        if(gu == gv) return {0, 0};
        int ans = 0;
        for(int l = LOG; l >= 0; l--) {
            if(gpar[l][gu] != gpar[l][gv]) {
                ans += 1<<l;
                gu = gpar[l][gu];
                gv = gpar[l][gv];
            }
        }
        assert(gu != gv && gpar[0][gu] == gpar[0][gv]);
        return {ans+1, ans+1};
    };
    vector<pair<int, int>> state(ng);
    int k; cin >> k;
    for(int q = 0; q < k; q++) {
        int a, b; cin >> a >> b; a--; b--;
        int ga = group[a], gb = group[b];
        auto [ca, cb] = climb_to_lca(climb_to_lca, ga, gb);
        if(state[ga].first < ca) state[ga].first = ca;
        if(state[gb].second < cb) state[gb].second = cb;
    }
    for(int g = ng-1; g >= 0; g--) {
        if(state[g].first > 0 && state[g].second > 0) {
            cout << "No\n";
            return false;
        }
        if(state[g].first > 0) {
            assert(g != 0);
            ans.emplace_back(groot[g], par[groot[g]]);
            if(state[gpar[0][g]].first < state[g].first-1) {
                state[gpar[0][g]].first = state[g].first;
            }
        } else if(state[g].second > 0) {
            assert(g != 0);
            ans.emplace_back(par[groot[g]], groot[g]);
            if(state[gpar[0][g]].second < state[g].second-1) {
                state[gpar[0][g]].second = state[g].second;
            }
        } else if(g != 0) {
            ans.emplace_back(groot[g], par[groot[g]]);
        }
    }
    cout << "Yes\n";
    for(auto [u, v] : ans) {
        cout << u+1 << ' ' << v+1 << '\n';
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(solve());
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 5632
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve(){
    int n, m; cin >> n >> m;
    vector g(n, vector<int>());
    for(int i = 0; i < m; i++) {
        int x, y; cin >> x >> y; x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> par(n);
    vector<vector<int>> child(n);
    vector<int> par_is_bridge(n);
    vector<pair<int, int>> ans;
    vector<int> ord(n, -1), low(n, -1);
    int idx = 0;
    auto dfs = [&](auto&& self, int u, int p) -> void {
        ord[u] = idx++;
        low[u] = ord[u];
        for(int v : g[u]) {
            if(v == p) continue;
            if(ord[v] != -1) {
                if(ord[v] < ord[u]) {
                    ans.emplace_back(u, v);
                    if(low[u] > ord[v]) low[u] = ord[v];
                }
            } else {
                child[u].push_back(v);
                par[v] = u;
                self(self, v, u);
                if(low[u] > low[v]) low[u] = low[v];
            }
        }
        if(p == -1) return;
        if(ord[p] < low[u]) par_is_bridge[u] = true;
        else ans.emplace_back(par[u], u);
    };
    dfs(dfs, 0, -1);
    vector<int> group(n, -1);
    group[0] = 0;
    vector<int> groot = {0};
    vector<int> gdepth = {0};
    auto dfs2 = [&](auto&& self, int u, int p) -> void {
        for(int v : child[u]) {
            if(par_is_bridge[v]) {
                group[v] = ssize(groot);
                groot.push_back(v);
                gdepth.push_back(gdepth[group[u]]+1);
            } else {
                group[v] = group[u];
            }
            self(self, v, u);
        }
    };
    dfs2(dfs2, 0, -1);
    int LOG = 16;
    int ng = ssize(groot);
    vector<vector<int>> gpar(LOG+1, vector<int>(ng, -1));
    for(int i = 0; i < ng; i++) {
        gpar[0][i] = i == 0 ? -1 : group[par[groot[i]]];
    }
    for(int l = 0; l < LOG; l++) for(int i = 0; i < ng; i++) {
        if(gpar[l][i] != -1) gpar[l+1][i] = gpar[l][gpar[l][i]];
    }
    auto climb = [&](int gu, int h) {
        for(int l = LOG; l >= 0; l--) {
            if(h >> l & 1) gu = gpar[l][gu];
            assert(gu != -1);
        }
        return gu;
    };
    auto climb_to_lca = [&](auto&& self, int gu, int gv) -> pair<int, int> {
        int du = gdepth[gu], dv = gdepth[gv];
        if(du > dv) {
            auto [cu, cv] = self(self, climb(gu, du-dv), gv);
            return {cu+(du-dv), cv};
        }
        if(du < dv) {
            auto [cu, cv] = self(self, gu, climb(gv, dv-du));
            return {cu, cv+(dv-du)};
        }
        if(gu == gv) return {0, 0};
        int ans = 0;
        for(int l = LOG; l >= 0; l--) {
            if(gpar[l][gu] != gpar[l][gv]) {
                ans += 1<<l;
                gu = gpar[l][gu];
                gv = gpar[l][gv];
            }
        }
        assert(gu != gv && gpar[0][gu] == gpar[0][gv]);
        return {ans+1, ans+1};
    };
    vector<pair<int, int>> state(ng);
    int k; cin >> k;
    for(int q = 0; q < k; q++) {
        int a, b; cin >> a >> b; a--; b--;
        int ga = group[a], gb = group[b];
        auto [ca, cb] = climb_to_lca(climb_to_lca, ga, gb);
        if(state[ga].first < ca) state[ga].first = ca;
        if(state[gb].second < cb) state[gb].second = cb;
    }
    for(int g = ng-1; g >= 0; g--) {
        if(state[g].first > 0 && state[g].second > 0) {
            cout << "No\n";
            return false;
        }
        if(state[g].first > 0) {
            assert(g != 0);
            ans.emplace_back(groot[g], par[groot[g]]);
            if(state[gpar[0][g]].first < state[g].first-1) {
                state[gpar[0][g]].first = state[g].first;
            }
        } else if(state[g].second > 0) {
            assert(g != 0);
            ans.emplace_back(par[groot[g]], groot[g]);
            if(state[gpar[0][g]].second < state[g].second-1) {
                state[gpar[0][g]].second = state[g].second;
            }
        } else if(g != 0) {
            ans.emplace_back(groot[g], par[groot[g]]);
        }
    }
    cout << "Yes\n";
    assert(ssize(ans) <= m);
    for(auto [u, v] : ans) {
        cout << u+1 << ' ' << v+1 << '\n';
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(solve());
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 5632
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve(){
    int n, m; cin >> n >> m;
    vector g(n, vector<int>());
    for(int i = 0; i < m; i++) {
        int x, y; cin >> x >> y; x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    vector<int> par(n);
    vector<vector<int>> child(n);
    vector<int> par_is_bridge(n);
    vector<pair<int, int>> ans;
    vector<int> ord(n, -1), low(n, -1);
    int idx = 0;
    auto dfs = [&](auto&& self, int u, int p) -> void {
        ord[u] = idx++;
        low[u] = ord[u];
        for(int v : g[u]) {
            if(v == p) continue;
            if(ord[v] != -1) {
                if(ord[v] < ord[u]) {
                    ans.emplace_back(u, v);
                    if(low[u] > ord[v]) low[u] = ord[v];
                }
            } else {
                child[u].push_back(v);
                par[v] = u;
                self(self, v, u);
                if(low[u] > low[v]) low[u] = low[v];
            }
        }
        if(p == -1) return;
        if(ord[p] < low[u]) par_is_bridge[u] = true;
        else ans.emplace_back(par[u], u);
    };
    dfs(dfs, 0, -1);
    vector<int> group(n, -1);
    group[0] = 0;
    vector<int> groot = {0};
    vector<int> gdepth = {0};
    auto dfs2 = [&](auto&& self, int u, int p) -> void {
        for(int v : child[u]) {
            if(par_is_bridge[v]) {
                group[v] = ssize(groot);
                groot.push_back(v);
                gdepth.push_back(gdepth[group[u]]+1);
            } else {
                group[v] = group[u];
            }
            self(self, v, u);
        }
    };
    dfs2(dfs2, 0, -1);
    int LOG = 16;
    int ng = ssize(groot);
    vector<vector<int>> gpar(LOG+1, vector<int>(ng, -1));
    for(int i = 0; i < ng; i++) {
        gpar[0][i] = i == 0 ? -1 : group[par[groot[i]]];
    }
    for(int l = 0; l < LOG; l++) for(int i = 0; i < ng; i++) {
        if(gpar[l][i] != -1) gpar[l+1][i] = gpar[l][gpar[l][i]];
    }
    auto climb = [&](int gu, int h) {
        for(int l = LOG; l >= 0; l--) {
            if(h >> l & 1) gu = gpar[l][gu];
            assert(gu != -1);
        }
        return gu;
    };
    auto climb_to_lca = [&](auto&& self, int gu, int gv) -> pair<int, int> {
        int du = gdepth[gu], dv = gdepth[gv];
        if(du > dv) {
            auto [cu, cv] = self(self, climb(gu, du-dv), gv);
            return {cu+(du-dv), cv};
        }
        if(du < dv) {
            auto [cu, cv] = self(self, gu, climb(gv, dv-du));
            return {cu, cv+(dv-du)};
        }
        if(gu == gv) return {0, 0};
        int ans = 0;
        for(int l = LOG; l >= 0; l--) {
            if(gpar[l][gu] != gpar[l][gv]) {
                ans += 1<<l;
                gu = gpar[l][gu];
                gv = gpar[l][gv];
            }
        }
        assert(gu != gv && gpar[0][gu] == gpar[0][gv]);
        return {ans+1, ans+1};
    };
    vector<pair<int, int>> state(ng);
    int k; cin >> k;
    for(int q = 0; q < k; q++) {
        int a, b; cin >> a >> b; a--; b--;
        int ga = group[a], gb = group[b];
        auto [ca, cb] = climb_to_lca(climb_to_lca, ga, gb);
        if(state[ga].first < ca) state[ga].first = ca;
        if(state[gb].second < cb) state[gb].second = cb;
    }
    for(int g = ng-1; g >= 0; g--) {
        if(state[g].first > 0 && state[g].second > 0) {
            cout << "No\n";
            return false;
        }
        if(state[g].first > 0) {
            assert(g != 0);
            ans.emplace_back(groot[g], par[groot[g]]);
            if(state[gpar[0][g]].first < state[g].first-1) {
                state[gpar[0][g]].first = state[g].first;
            }
        } else if(state[g].second > 0) {
            assert(g != 0);
            ans.emplace_back(par[groot[g]], groot[g]);
            if(state[gpar[0][g]].second < state[g].second-1) {
                state[gpar[0][g]].second = state[g].second;
            }
        } else if(g != 0) {
            ans.emplace_back(groot[g], par[groot[g]]);
        }
    }
    cout << "Yes\n";
    for(auto [u, v] : ans) {
        cout << u+1 << ' ' << v+1 << '\n';
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(solve());
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 5632
final_rank: 12

code_snippet: // AOJ #1408 One-Way Conveyors
// 2025.2.15

#include <bits/stdc++.h>
using namespace std;
 
struct Edge {
    int u, v;
    int id;
    bool bridge;
};
 
int n, m;
vector<vector<int>> g;
vector<Edge> edges;
 
vector<int> tin, low;
int timer_dfs;
 
void dfs_bridges(int v, int parent_edge) {
    tin[v] = low[v] = timer_dfs++;
    for (int ei : g[v]) {
        Edge &e = edges[ei];
        int nxt = (e.u == v ? e.v : e.u);
        if(e.id == parent_edge) continue;
        if(tin[nxt] == -1){
            dfs_bridges(nxt, e.id);
            low[v] = min(low[v], low[nxt]);
            if(low[nxt] > tin[v]) e.bridge = true;
        } else low[v] = min(low[v], tin[nxt]);
    }
}
 
vector<int> comp;
int compCount;
 
void dfs_comp(int v, int cid, vector<bool> &visited) {
    visited[v] = true;
    comp[v] = cid;
    for (int ei : g[v]) {
        Edge &e = edges[ei];
        if(e.bridge) continue;
        int nxt = (e.u == v ? e.v : e.u);
        if(!visited[nxt]) dfs_comp(nxt, cid, visited);
    }
}
 
struct TreeEdge {
    int to;
    int origEdgeId;
};
 
vector<vector<TreeEdge>> tree;
vector<pair<int,int>> bridgeComp;
 
vector<int> parentT, depthT, heavy, head, pos, subSize;
int curPos = 0;
 
int dfs_hld(int v, int p) {
    parentT[v] = p;
    depthT[v] = (p == -1 ? 0 : depthT[p] + 1);
    int size = 1, maxSub = 0;
    heavy[v] = -1;
    for(auto &te : tree[v]){
        int nxt = te.to;
        if(nxt == p) continue;
        int sub = dfs_hld(nxt, v);
        if(sub > maxSub){
            maxSub = sub;
            heavy[v] = nxt;
        }
        size += sub;
    }
    subSize[v] = size;
    return size;
}
 
void decompose(int v, int h) {
    head[v] = h;
    pos[v] = curPos++;
    if(heavy[v] != -1) decompose(heavy[v], h);
    for(auto &te : tree[v]){
        int nxt = te.to;
        if(nxt == parentT[v] || nxt == heavy[v]) continue;
        decompose(nxt, nxt);
    }
}
 
struct BIT {
    int n;
    vector<int> fenw;
    BIT(int n): n(n) { fenw.assign(n+1,0); }
    void update(int i, int delta) {
        for(++i; i <= n; i += i & -i) fenw[i] += delta;
    }
    void rangeUpdate(int l, int r, int delta) {
        if(l > r) return;
        update(l, delta);
        update(r+1, -delta);
    }
    int query(int i) {
        int s = 0;
        for(++i; i; i -= i & -i) s += fenw[i];
        return s;
    }
};
 
void hldPathUpdate(int u, int anc, int delta, BIT &bit) {
    while(head[u] != head[anc]){
        bit.rangeUpdate(pos[head[u]], pos[u], delta);
        u = parentT[head[u]];
    }
    if(u == anc) return;
    bit.rangeUpdate(pos[anc]+1, pos[u], delta);
}
 
int lcaT(int u, int v) {
    while(head[u] != head[v]){
        if(depthT[head[u]] > depthT[head[v]]) u = parentT[head[u]];
        else v = parentT[head[v]];
    }
    return depthT[u] < depthT[v] ? u : v;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    cin >> n >> m;
    g.assign(n, vector<int>());
    edges.resize(m);
    for (int i = 0; i < m; i++){
        int u, v; 
        cin >> u >> v;
        u--; v--;
        edges[i] = {u, v, i, false};
        g[u].push_back(i);
        g[v].push_back(i);
    }
    tin.assign(n, -1);
    low.assign(n, -1);
    timer_dfs = 0;
    dfs_bridges(0, -1);
 
    comp.assign(n, -1);
    vector<bool> visited(n, false);
    compCount = 0;
    for (int i = 0; i < n; i++){
        if(!visited[i]){
            dfs_comp(i, compCount, visited);
            compCount++;
        }
    }
 
    tree.assign(compCount, vector<TreeEdge>());
    bridgeComp.resize(m, {-1,-1});
    for (int i = 0; i < m; i++){
        if(!edges[i].bridge) continue;
        int cu = comp[edges[i].u], cv = comp[edges[i].v];
        tree[cu].push_back({cv, i});
        tree[cv].push_back({cu, i});
        bridgeComp[i] = {cu, cv};
    }
 
    parentT.assign(compCount, -1);
    depthT.assign(compCount, 0);
    heavy.assign(compCount, -1);
    head.assign(compCount, 0);
    pos.assign(compCount, 0);
    subSize.assign(compCount, 0);
    if(compCount > 0){
        dfs_hld(0, -1);
        curPos = 0;
        decompose(0, 0);
    }
 
    int k; 
    cin >> k;
    BIT bitUp(compCount), bitDown(compCount);
    for (int i = 0; i < k; i++){
        int a, b; 
        cin >> a >> b; 
        a--; b--;
        int ca = comp[a], cb = comp[b];
        if(ca == cb) continue;
        int l = lcaT(ca, cb);
        if(ca != l) hldPathUpdate(ca, l, 1, bitUp);
        if(cb != l) hldPathUpdate(cb, l, 1, bitDown);
    }
 
    vector<int> forcedDir(compCount, 0);
    bool possible = true;
    for (int v = 0; v < compCount; v++){
        if(v == 0) continue;
        int upVal = bitUp.query(pos[v]);
        int downVal = bitDown.query(pos[v]);
        if(upVal > 0 && downVal > 0){
            possible = false;
            break;
        }
        if(upVal > 0) forcedDir[v] = -1;
        else          forcedDir[v] = 1;
    }
 
    if(!possible){
        cout << "No" << endl;
        return 0;
    }
 
    vector<pair<int,int>> ans(m, {-1,-1});
 
    for (int v = 1; v < compCount; v++){
        int p = parentT[v];
        int bridgeId = -1;
        for(auto &te : tree[v]){
            if(te.to == p){
                bridgeId = te.origEdgeId;
                break;
            }
        }
        if(bridgeId == -1) continue;
        Edge &be = edges[bridgeId];
        if(forcedDir[v] == 1){
            if(comp[be.u] == p && comp[be.v] == v)
                ans[bridgeId] = {be.u+1, be.v+1};
            else if(comp[be.u] == v && comp[be.v] == p)
                ans[bridgeId] = {be.v+1, be.u+1};
        } else {
            if(comp[be.u] == v && comp[be.v] == p)
                ans[bridgeId] = {be.u+1, be.v+1};
            else if(comp[be.u] == p && comp[be.v] == v)
                ans[bridgeId] = {be.v+1, be.u+1};
        }
    }
 
    vector<vector<pair<int,int>>> adjNonBridge(n);
    for (int i = 0; i < m; i++){
        if(edges[i].bridge) continue;
        int u = edges[i].u, v = edges[i].v;
        adjNonBridge[u].push_back({v, i});
        adjNonBridge[v].push_back({u, i});
    }
    vector<bool> visitedNon(n, false);
    vector<bool> usedEdge(m, false);
    vector<int> disc(n, -1);
    int timeCounter = 0;
    function<void(int)> dfsNonBridge = [&](int u) {
        visitedNon[u] = true;
        disc[u] = timeCounter++;
        for(auto &p : adjNonBridge[u]){
            int v = p.first, eid = p.second;
            if(usedEdge[eid]) continue;
            usedEdge[eid] = true;
            if(!visitedNon[v]){
                ans[eid] = {u+1, v+1};
                dfsNonBridge(v);
            } else {
                if(disc[u] < disc[v])
                    ans[eid] = {v+1, u+1};
                else
                    ans[eid] = {u+1, v+1};
            }
        }
    };
    for (int i = 0; i < n; i++){
        if(!visitedNon[i] && !adjNonBridge[i].empty()){
            dfsNonBridge(i);
        }
    }
    for (int i = 0; i < m; i++){
        if(ans[i].first == -1){
            Edge &e = edges[i];
            ans[i] = {e.u+1, e.v+1};
        }
    }
    cout << "Yes" << endl;
    for (int i = 0; i < m; i++){
        cout << ans[i].first << " " << ans[i].second << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 10712
final_rank: 4

code_snippet: // AOJ #1408 One-Way Conveyors
// 2025.2.15

#include <bits/stdc++.h>
using namespace std;
 
struct Edge {
    int u, v;
    int id;
    bool bridge;
};
 
int n, m;
vector<vector<int>> g;
vector<Edge> edges;
 
vector<int> tin, low;
int timer_dfs;
 
void dfs_bridges(int v, int parent_edge) {
    tin[v] = low[v] = timer_dfs++;
    for (int ei : g[v]) {
        Edge &e = edges[ei];
        int nxt = (e.u == v ? e.v : e.u);
        if(e.id == parent_edge) continue;
        if(tin[nxt] == -1){
            dfs_bridges(nxt, e.id);
            low[v] = min(low[v], low[nxt]);
            if(low[nxt] > tin[v]){
                e.bridge = true;
            }
        } else {
            low[v] = min(low[v], tin[nxt]);
        }
    }
}
 
vector<int> comp;
int compCount;
 
void dfs_comp(int v, int cid, vector<bool> &visited) {
    visited[v] = true;
    comp[v] = cid;
    for (int ei : g[v]) {
        Edge &e = edges[ei];
        if(e.bridge) continue;
        int nxt = (e.u == v ? e.v : e.u);
        if(!visited[nxt])
            dfs_comp(nxt, cid, visited);
    }
}
 
struct TreeEdge {
    int to;
    int origEdgeId;
};
 
vector<vector<TreeEdge>> tree;
 
vector<pair<int,int>> bridgeComp;
 
int compsize;
vector<int> parentT, depthT, heavy, head, pos, subSize;
 
int dfs_hld(int v, int p) {
    parentT[v] = p;
    depthT[v] = (p == -1 ? 0 : depthT[p] + 1);
    int size = 1;
    int maxSub = 0;
    heavy[v] = -1;
    for(auto &te : tree[v]){
        int nxt = te.to;
        if(nxt == p) continue;
        int sub = dfs_hld(nxt, v);
        if(sub > maxSub){
            maxSub = sub;
            heavy[v] = nxt;
        }
        size += sub;
    }
    subSize[v] = size;
    return size;
}
 
int curPos = 0;
void decompose(int v, int h) {
    head[v] = h;
    pos[v] = curPos++;
    if(heavy[v] != -1)
        decompose(heavy[v], h);
    for(auto &te : tree[v]){
        int nxt = te.to;
        if(nxt == parentT[v] || nxt == heavy[v]) continue;
        decompose(nxt, nxt);
    }
}
 
struct BIT {
    int n;
    vector<int> fenw;
    BIT(int n): n(n) { fenw.assign(n+1,0); }
    void update(int i, int delta) {
        for(++i; i <= n; i += i & -i)
            fenw[i] += delta;
    }
    void rangeUpdate(int l, int r, int delta) {
        if(l > r) return;
        update(l, delta);
        update(r+1, -delta);
    }
    int query(int i) {
        int s = 0;
        for(++i; i; i -= i & -i)
            s += fenw[i];
        return s;
    }
};
 
void hldPathUpdate(int u, int anc, int delta, BIT &bit) {
    while(head[u] != head[anc]){
        bit.rangeUpdate(pos[head[u]], pos[u], delta);
        u = parentT[head[u]];
    }
    if(u == anc) return;
    bit.rangeUpdate(pos[anc]+1, pos[u], delta);
}
 
int lcaT(int u, int v) {
    while(head[u] != head[v]){
        if(depthT[head[u]] > depthT[head[v]])
            u = parentT[head[u]];
        else
            v = parentT[head[v]];
    }
    return depthT[u] < depthT[v] ? u : v;
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;
    g.assign(n, vector<int>());
    edges.resize(m);
    for (int i = 0; i < m; i++){
        int u,v; 
        cin >> u >> v;
        u--; v--;
        edges[i] = {u, v, i, false};
        g[u].push_back(i);
        g[v].push_back(i);
    }
    tin.assign(n, -1);
    low.assign(n, -1);
    timer_dfs = 0;
    dfs_bridges(0, -1);
 
    comp.assign(n, -1);
    vector<bool> visited(n, false);
    compCount = 0;
    for (int i = 0; i < n; i++){
        if(!visited[i]){
            dfs_comp(i, compCount, visited);
            compCount++;
        }
    }
 
    tree.assign(compCount, vector<TreeEdge>());
    bridgeComp.resize(m, {-1,-1});
    for (int i = 0; i < m; i++){
        if(!edges[i].bridge) continue;
        int cu = comp[edges[i].u], cv = comp[edges[i].v];
        tree[cu].push_back({cv, i});
        tree[cv].push_back({cu, i});
        bridgeComp[i] = {cu, cv};
    }
 
    parentT.assign(compCount, -1);
    depthT.assign(compCount, 0);
    heavy.assign(compCount, -1);
    head.assign(compCount, 0);
    pos.assign(compCount, 0);
    subSize.assign(compCount, 0);
    if(compCount > 0){
        dfs_hld(0, -1);
        curPos = 0;
        decompose(0, 0);
    }
 
    int k; 
    cin >> k;
    BIT bitUp(compCount), bitDown(compCount);
 
    for (int i = 0; i < k; i++){
        int a, b; 
        cin >> a >> b; 
        a--; b--;
        int ca = comp[a], cb = comp[b];
        if(ca == cb) continue;
        int l = lcaT(ca, cb);
        if(ca != l){
            hldPathUpdate(ca, l, 1, bitUp);
        }
        if(cb != l){
            hldPathUpdate(cb, l, 1, bitDown);
        }
    }
 
    vector<int> forcedDir(compCount, 0);
    bool possible = true;
    for (int v = 0; v < compCount; v++){
        if(v == 0) continue;
        int upVal = bitUp.query(pos[v]);
        int downVal = bitDown.query(pos[v]);
        if(upVal > 0 && downVal > 0){
            possible = false;
            break;
        }
        if(upVal > 0){
            forcedDir[v] = -1;
        } else {
            forcedDir[v] = 1;
        }
    }
 
    if(!possible){
        cout << "No" << endl;
        return 0;
    }
 
    vector<pair<int,int>> ans(m, {-1,-1});
    vector<int> usedBridge(m, 0);
    for (int v = 1; v < compCount; v++){
        int p = parentT[v];
        int bridgeId = -1;
        for(auto &te : tree[v]){
            if(te.to == p){
                bridgeId = te.origEdgeId;
                break;
            }
        }
        if(bridgeId == -1) continue;
        Edge &be = edges[bridgeId];
        if(forcedDir[v] == 1){
            if(comp[be.u] == p && comp[be.v] == v)
                ans[bridgeId] = {be.u+1, be.v+1};
            else if(comp[be.u] == v && comp[be.v] == p)
                ans[bridgeId] = {be.v+1, be.u+1};
        } else {
            if(comp[be.u] == v && comp[be.v] == p)
                ans[bridgeId] = {be.u+1, be.v+1};
            else if(comp[be.u] == p && comp[be.v] == v)
                ans[bridgeId] = {be.v+1, be.u+1};
        }
        usedBridge[bridgeId] = 1;
    }
 
    vector<vector<pair<int,int>>> compAdj(compCount);
    for (int i = 0; i < m; i++){
        if(edges[i].bridge) continue;
        int ccomp = comp[edges[i].u];
        compAdj[ccomp].push_back({edges[i].u, i});
        compAdj[ccomp].push_back({edges[i].v, i});
    }
    vector<int> doneEdge(m,0);
    vector<int> compVisited(n,0), disc(n,0);
    int timeCounter = 0;
    function<void(int,int,int)> dfs2ecc = [&](int u, int parent, int parentEdge) {
        compVisited[u] = 1;
        disc[u] = timeCounter++;
        for(auto &p : compAdj[ comp[u] ]){
            int w = p.first;
            int eid = p.second;
            if(doneEdge[eid]) continue;
            doneEdge[eid] = 1;
            if(!compVisited[w]){
                ans[eid] = {u+1, w+1};
                dfs2ecc(w, u, eid);
            } else {
                if(disc[u] < disc[w])
                    ans[eid] = {w+1, u+1};
                else
                    ans[eid] = {u+1, w+1};
            }
        }
    };
    for (int i = 0; i < n; i++){
        if(!compVisited[i]){
            if(!compAdj[ comp[i] ].empty())
                dfs2ecc(i, -1, -1);
        }
    }
    for (int i = 0; i < m; i++){
        if(ans[i].first == -1){
            Edge &e = edges[i];
            ans[i] = {min(e.u, e.v)+1, max(e.u, e.v)+1};
        }
    }
    cout << "Yes" << endl;
    for (int i = 0; i < m; i++){
        cout << ans[i].first << " " << ans[i].second << endl;
    }
    return 0;
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 5688
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
#define rep(i,n) for(int i=0; i<int(n); i++)

struct TECC{
    vector<int> tree;
    vector<int> mapping;
    vector<pair<int,int>> way;
    int treen;
    TECC(int N, vector<pair<int,int>> graph){
        vector<vector<pair<int,int>>> adj(N);
        int M = graph.size();
        rep(e,M){
            auto [u,v] = graph[e];
            adj[u].push_back({v,e});
            adj[v].push_back({u,e});
        }
        way.resize(M);
        vector<int> vis(N);
        vector<int> parent(N, -1);
        vector<int> seen_parent_link(N);
        vector<int> dfsi(N);
        vector<int> ord;
        vector<int> low(N, N);
        int dfsix = 0;
        auto dfs = [&](auto& dfs, int v) -> void {
            vis[v] = 1;
            ord.push_back(v);
            dfsi[v] = dfsix++;
            for(auto [w,e] : adj[v]){
                if(parent[v] == w){
                    if(exchange(seen_parent_link[v], 1)){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    } continue;
                }
                if(vis[w]){
                    if(dfsi[v] > dfsi[w]){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    }
                    continue;
                }
                parent[w] = v;
                way[e] = {v,w};
                dfs(dfs, w);
                low[v] = min(low[v], low[w]);
            }
        };
        dfs(dfs, 0);
        mapping.resize(N);
        int mapi = 1;
        for(int i=1; i<N; i++){
            int v = ord[i];
            if(low[v] < dfsi[v]){
                mapping[v] = mapping[parent[v]];
            } else {
                mapping[v] = mapi++;
            }
        }
        treen = mapi;
    }
};

vector<pair<int,int>> solvetree(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    vector<vector<pair<int,int>>> adj(N);
    int M = A.size();
    rep(e,M){
        auto [u,v] = A[e];
        adj[u].push_back({v,e});
        adj[v].push_back({u,e});
    }
    vector<int> vis(N);
    vector<int> parent(N, -1);
    vector<int> dfsi(N);
    vector<int> ord;
    vector<int> dep(N);
    int dfsix = 0;
    auto dfs = [&](auto& dfs, int v) -> void {
        vis[v] = 1;
        ord.push_back(v);
        dfsi[v] = dfsix++;
        for(auto [w,e] : adj[v]){
            if(vis[w]) continue;
            parent[w] = v;
            dep[w] = dep[v] + 1;
            dfs(dfs, w);
        }
    };
    dfs(dfs, 0);
    vector<vector<int>> PP(20, parent);
    PP[0][0] = 0;
    rep(d,19) rep(i,N) PP[d+1][i] = PP[d][PP[d][i]];
    auto lca = [&](int u, int v){
        if(dep[u] > dep[v]) swap(u,v);
        for(int d=19; d>=0; d--) if(dep[u] <= dep[PP[d][v]]) v = PP[d][v];
        if(u == v) return u;
        for(int d=19; d>=0; d--) if(PP[d][u] != PP[d][v]){
            v = PP[d][v];  u = PP[d][u];
        }
        return parent[u];
    };
    vector<int> imosup(N), imosdn(N);
    for(auto [u,v] : B){
        int g = lca(u,v);
        imosup[u] += 1;
        imosup[g] -= 1;
        imosdn[v] += 1;
        imosdn[g] -= 1;
    }
    for(int i=N-1; i>=0; i--){
        int v = ord[i]; int w = parent[v];
        imosup[w] += imosup[v];
        imosdn[w] += imosdn[v];
    }
    //for(auto a : imosup){ cout << a << " "; } cout << endl;
    //for(auto a : imosdn){ cout << a << " "; } cout << endl;
    vector<pair<int,int>> res;
    for(auto [u,v] : A){
        if(u != parent[v]) swap(u,v);
        if(imosup[v] != 0 && imosdn[v] != 0) return {{-1,-1}};
        if(imosup[v] != 0) swap(u,v);
        res.push_back({u,v});
    }
    return res;
}

vector<pair<int,int>> solve(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    auto tecc = TECC(N, A);
    auto teccmap = tecc.mapping;
    int M = A.size();
    int n = tecc.treen;
    vector<pair<int,int>> a;
    vector<int> eid;
    rep(e,M){
        auto [u,v] = A[e];
        if(teccmap[u] != teccmap[v]){
            a.emplace_back(teccmap[u], teccmap[v]);
            eid.push_back(e);
        }
    }
    for(auto& [u,v] : B){
        u = teccmap[u];
        v = teccmap[v];
    }
    //for(auto a : teccmap){ cout << a << " "; } cout << endl;
    auto ans = tecc.way;
    auto q = solvetree(n, a, B);
    if(q == vector<pair<int,int>>{{-1,-1}}) return q;
    //for(auto a : q){ cout << a.first << "-" << a.second << " "; } cout << endl;
    //for(auto a : eid){ cout << a << " "; } cout << endl;
    rep(ei,a.size()){
        auto [u,v] = q[ei];
        if(u != teccmap[ans[eid[ei]].first]){
            swap(ans[eid[ei]].first, ans[eid[ei]].second);
        }
    }
    return ans;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N, M; cin >> N >> M;
    vector<pair<int,int>> graph(M);
    for(auto&[u,v] : graph){ cin >> u >> v; u--; v--; }
    int K; cin >> K;
    vector<pair<int,int>> cons(K);
    for(auto&[u,v] : cons){ cin >> u >> v; u--; v--; }
    auto ans = solve(N, graph, cons);
    if(ans.size() == 1 && ans[0].first == -1){
        cout << "No\n";
    } else {
        cout << "Yes\n";
        for(auto [u,v] : ans) cout << (u+1) << ' ' << (v+1) << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 10108
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
#define rep(i,n) for(int i=0; i<int(n); i++)

struct TECC{
    vector<int> tree;
    vector<int> mapping;
    vector<pair<int,int>> way;
    int treen;
    TECC(int N, vector<pair<int,int>> graph){
        vector<vector<pair<int,int>>> adj(N);
        int M = graph.size();
        rep(e,M){
            auto [u,v] = graph[e];
            adj[u].push_back({v,e});
            adj[v].push_back({u,e});
        }
        way.resize(M);
        vector<int> vis(N);
        vector<int> parent(N, -1);
        vector<int> seen_parent_link(N);
        vector<int> dfsi(N);
        vector<int> ord;
        vector<int> low(N, N);
        int dfsix = 0;
        auto dfs = [&](auto& dfs, int v) -> void {
            vis[v] = 1;
            ord.push_back(v);
            dfsi[v] = dfsix++;
            for(auto [w,e] : adj[v]){
                if(parent[v] == w){
                    if(exchange(seen_parent_link[v], 1)){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    } continue;
                }
                if(vis[w]){
                    if(dfsi[v] > dfsi[w]){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    }
                    continue;
                }
                parent[w] = v;
                way[e] = {v,w};
                dfs(dfs, w);
                low[v] = min(low[v], low[w]);
            }
        };
        dfs(dfs, 0);
        mapping.resize(N);
        int mapi = 1;
        for(int i=1; i<N; i++){
            int v = ord[i];
            if(low[v] < dfsi[v]){
                mapping[v] = mapping[parent[v]];
            } else {
                mapping[v] = mapi++;
            }
        }
        treen = mapi;
    }
};

vector<pair<int,int>> solvetree(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    vector<vector<pair<int,int>>> adj(N);
    int M = A.size();
    rep(e,M){
        auto [u,v] = A[e];
        adj[u].push_back({v,e});
        adj[v].push_back({u,e});
    }
    vector<int> vis(N);
    vector<int> parent(N, -1);
    vector<int> dfsi(N);
    vector<int> ord;
    vector<int> dep(N);
    int dfsix = 0;
    auto dfs = [&](auto& dfs, int v) -> void {
        vis[v] = 1;
        ord.push_back(v);
        dfsi[v] = dfsix++;
        for(auto [w,e] : adj[v]){
            if(vis[w]) continue;
            parent[w] = v;
            dep[w] = dep[v] + 1;
            dfs(dfs, w);
        }
    };
    dfs(dfs, 0);
    vector<vector<int>> PP(20, parent);
    PP[0][0] = 0;
    rep(d,19) rep(i,N) PP[d+1][i] = PP[d][PP[d][i]];
    auto lca = [&](int u, int v){
        if(dep[u] > dep[v]) swap(u,v);
        for(int d=19; d>=0; d--) if(dep[u] <= dep[PP[d][v]]) v = PP[d][v];
        if(u == v) return u;
        for(int d=19; d>=0; d--) if(PP[d][u] != PP[d][v]){
            v = PP[d][v];  u = PP[d][v];
        }
        return parent[u];
    };
    vector<int> imosup(N), imosdn(N);
    for(auto [u,v] : B){
        int g = lca(u,v);
        imosup[u] += 1;
        imosup[g] -= 1;
        imosdn[v] += 1;
        imosdn[g] -= 1;
    }
    for(int i=N-1; i>=0; i--){
        int v = ord[i]; int w = parent[v];
        imosup[w] += imosup[v];
        imosdn[w] += imosdn[v];
    }
    //for(auto a : imosup){ cout << a << " "; } cout << endl;
    //for(auto a : imosdn){ cout << a << " "; } cout << endl;
    vector<pair<int,int>> res;
    for(auto [u,v] : A){
        if(u != parent[v]) swap(u,v);
        if(imosup[v] != 0 && imosdn[v] != 0) return {{-1,-1}};
        if(imosup[v] != 0) swap(u,v);
        res.push_back({u,v});
    }
    return res;
}

vector<pair<int,int>> solve(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    auto tecc = TECC(N, A);
    auto teccmap = tecc.mapping;
    int M = A.size();
    int n = tecc.treen;
    vector<pair<int,int>> a;
    vector<int> eid;
    rep(e,M){
        auto [u,v] = A[e];
        if(teccmap[u] != teccmap[v]){
            a.emplace_back(teccmap[u], teccmap[v]);
            eid.push_back(e);
        }
    }
    for(auto& [u,v] : B){
        u = teccmap[u];
        v = teccmap[v];
    }
    //for(auto a : teccmap){ cout << a << " "; } cout << endl;
    auto ans = tecc.way;
    auto q = solvetree(n, a, B);
    if(q == vector<pair<int,int>>{{-1,-1}}) return q;
    //for(auto a : q){ cout << a.first << "-" << a.second << " "; } cout << endl;
    //for(auto a : eid){ cout << a << " "; } cout << endl;
    rep(ei,a.size()){
        auto [u,v] = q[ei];
        if(u != teccmap[ans[eid[ei]].first]){
            swap(ans[eid[ei]].first, ans[eid[ei]].second);
        }
    }
    return ans;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N, M; cin >> N >> M;
    vector<pair<int,int>> graph(M);
    for(auto&[u,v] : graph){ cin >> u >> v; u--; v--; }
    int K; cin >> K;
    vector<pair<int,int>> cons(K);
    for(auto&[u,v] : cons){ cin >> u >> v; u--; v--; }
    auto ans = solve(N, graph, cons);
    if(ans.size() == 1 && ans[0].first == -1){
        cout << "No\n";
    } else {
        cout << "Yes\n";
        for(auto [u,v] : ans) cout << (u+1) << ' ' << (v+1) << '\n';
    }
    return 0;
}
accuracy: 0.15151515151515152
time_ms: 10
memory_kb: 6864
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
#define rep(i,n) for(int i=0; i<int(n); i++)

struct TECC{
    vector<int> tree;
    vector<int> mapping;
    vector<pair<int,int>> way;
    int treen;
    TECC(int N, vector<pair<int,int>> graph){
        vector<vector<pair<int,int>>> adj(N);
        int M = graph.size();
        rep(e,M){
            auto [u,v] = graph[e];
            adj[u].push_back({v,e});
            adj[v].push_back({u,e});
        }
        way.resize(M);
        vector<int> vis(N);
        vector<int> parent(N, -1);
        vector<int> seen_parent_link(N);
        vector<int> dfsi(N);
        vector<int> ord;
        vector<int> low(N, N);
        int dfsix = 0;
        auto dfs = [&](auto& dfs, int v) -> void {
            vis[v] = 1;
            ord.push_back(v);
            dfsi[v] = dfsix++;
            for(auto [w,e] : adj[v]){
                if(parent[v] == w){
                    if(exchange(seen_parent_link[v], 1)){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    } continue;
                }
                if(vis[w]){
                    if(dfsi[v] > dfsi[w]){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    }
                    continue;
                }
                parent[w] = v;
                way[e] = {v,w};
                dfs(dfs, w);
                low[v] = min(low[v], low[w]);
            }
        };
        dfs(dfs, 0);
        mapping.resize(N);
        int mapi = 1;
        for(int i=1; i<N; i++){
            int v = ord[i];
            if(low[v] < dfsi[v]){
                mapping[v] = mapping[parent[v]];
            } else {
                mapping[v] = mapi++;
            }
        }
        treen = mapi;
    }
};

vector<pair<int,int>> solvetree(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    vector<vector<pair<int,int>>> adj(N);
    int M = A.size();
    rep(e,M){
        auto [u,v] = A[e];
        adj[u].push_back({v,e});
        adj[v].push_back({u,e});
    }
    vector<int> vis(N);
    vector<int> parent(N, -1);
    vector<int> dfsi(N);
    vector<int> ord;
    vector<int> dep(N);
    int dfsix = 0;
    auto dfs = [&](auto& dfs, int v) -> void {
        vis[v] = 1;
        ord.push_back(v);
        dfsi[v] = dfsix++;
        for(auto [w,e] : adj[v]){
            if(vis[w]) continue;
            parent[w] = v;
            dep[w] = dep[v] + 1;
            dfs(dfs, w);
        }
    };
    dfs(dfs, 0);
    vector<vector<int>> PP(20, parent);
    PP[0][0] = 0;
    rep(d,19) rep(i,N) PP[d+1][i] = PP[d][PP[d][i]];
    auto lca = [&](int u, int v){
        if(dep[u] > dep[v]) swap(u,v);
        for(int d=19; d>=0; d--) if(dep[u] <= dep[PP[d][v]]) v = PP[d][v];
        if(u == v) return u;
        for(int d=19; d>=0; d--) if(PP[d][u] != PP[d][v]){
            v = PP[d][v];  u + PP[d][v];
        }
        return parent[u];
    };
    vector<int> imosup(N), imosdn(N);
    for(auto [u,v] : B){
        int g = lca(u,v);
        imosup[u] += 1;
        imosup[g] -= 1;
        imosdn[v] += 1;
        imosdn[g] -= 1;
    }
    for(int i=N-1; i>=0; i--){
        int v = ord[i]; int w = parent[v];
        imosup[w] += imosup[v];
        imosdn[w] += imosdn[v];
    }
    //for(auto a : imosup){ cout << a << " "; } cout << endl;
    //for(auto a : imosdn){ cout << a << " "; } cout << endl;
    vector<pair<int,int>> res;
    for(auto [u,v] : A){
        if(u != parent[v]) swap(u,v);
        if(imosup[v] != 0 && imosdn[v] != 0) return {{-1,-1}};
        if(imosup[v] != 0) swap(u,v);
        res.push_back({u,v});
    }
    return res;
}

vector<pair<int,int>> solve(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    auto tecc = TECC(N, A);
    auto teccmap = tecc.mapping;
    int M = A.size();
    int n = tecc.treen;
    vector<pair<int,int>> a;
    vector<int> eid;
    rep(e,M){
        auto [u,v] = A[e];
        if(teccmap[u] != teccmap[v]){
            a.emplace_back(teccmap[u], teccmap[v]);
            eid.push_back(e);
        }
    }
    for(auto& [u,v] : B){
        u = teccmap[u];
        v = teccmap[v];
    }
    //for(auto a : teccmap){ cout << a << " "; } cout << endl;
    auto ans = tecc.way;
    auto q = solvetree(n, a, B);
    if(q == vector<pair<int,int>>{{-1,-1}}) return q;
    //for(auto a : q){ cout << a.first << "-" << a.second << " "; } cout << endl;
    //for(auto a : eid){ cout << a << " "; } cout << endl;
    rep(ei,a.size()){
        auto [u,v] = q[ei];
        if(u != teccmap[ans[eid[ei]].first]){
            swap(ans[eid[ei]].first, ans[eid[ei]].second);
        }
    }
    return ans;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N, M; cin >> N >> M;
    vector<pair<int,int>> graph(M);
    for(auto&[u,v] : graph){ cin >> u >> v; u--; v--; }
    int K; cin >> K;
    vector<pair<int,int>> cons(K);
    for(auto&[u,v] : cons){ cin >> u >> v; u--; v--; }
    auto ans = solve(N, graph, cons);
    if(ans.size() == 1 && ans[0].first == -1){
        cout << "No\n";
    } else {
        cout << "Yes\n";
        for(auto [u,v] : ans) cout << (u+1) << ' ' << (v+1) << '\n';
    }
    return 0;
}
accuracy: 0.15151515151515152
time_ms: 10
memory_kb: 6824
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;
#define rep(i,n) for(int i=0; i<int(n); i++)

struct TECC{
    vector<int> tree;
    vector<int> mapping;
    vector<pair<int,int>> way;
    int treen;
    TECC(int N, vector<pair<int,int>> graph){
        vector<vector<pair<int,int>>> adj(N);
        int M = graph.size();
        rep(e,M){
            auto [u,v] = graph[e];
            adj[u].push_back({v,e});
            adj[v].push_back({u,e});
        }
        way.resize(M);
        vector<int> vis(N);
        vector<int> parent(N, -1);
        vector<int> seen_parent_link(N);
        vector<int> dfsi(N);
        vector<int> ord;
        vector<int> low(N, N);
        int dfsix = 0;
        auto dfs = [&](auto& dfs, int v) -> void {
            vis[v] = 1;
            ord.push_back(v);
            dfsi[v] = dfsix++;
            for(auto [w,e] : adj[v]){
                if(parent[v] == w){
                    if(exchange(seen_parent_link[v], 1)){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    } continue;
                }
                if(vis[w]){
                    if(dfsi[v] > dfsi[w]){
                        low[v] = min(low[v], dfsi[w]);
                        way[e] = {v,w};
                    }
                    continue;
                }
                parent[w] = v;
                way[e] = {v,w};
                dfs(dfs, w);
                low[v] = min(low[v], low[w]);
            }
        };
        dfs(dfs, 0);
        mapping.resize(N);
        int mapi = 1;
        for(int i=1; i<N; i++){
            int v = ord[i];
            if(low[v] < dfsi[v]){
                mapping[v] = mapping[parent[v]];
            } else {
                mapping[v] = mapi++;
            }
        }
        treen = mapi;
    }
};

vector<pair<int,int>> solvetree(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    vector<vector<pair<int,int>>> adj(N);
    int M = A.size();
    rep(e,M){
        auto [u,v] = A[e];
        adj[u].push_back({v,e});
        adj[v].push_back({u,e});
    }
    vector<int> vis(N);
    vector<int> parent(N, -1);
    vector<int> dfsi(N);
    vector<int> ord;
    vector<int> dep(N);
    int dfsix = 0;
    auto dfs = [&](auto& dfs, int v) -> void {
        vis[v] = 1;
        ord.push_back(v);
        dfsi[v] = dfsix++;
        for(auto [w,e] : adj[v]){
            if(vis[w]) continue;
            parent[w] = v;
            dep[w] = dep[v] + 1;
            dfs(dfs, w);
        }
    };
    dfs(dfs, 0);
    vector<vector<int>> PP(20, parent);
    PP[0][0] = 0;
    rep(d,19) rep(i,N) PP[d+1][i] = PP[d][PP[d][i]];
    auto lca = [&](int u, int v){
        if(dep[u] > dep[v]) swap(u,v);
        for(int d=19; d>=0; d--) if(dep[u] <= dep[PP[d][v]]) v = PP[d][v];
        if(u == v) return u;
        for(int d=19; d>=0; d--) if(PP[d][u] != PP[d][v]){
            v = PP[d][v];  u + PP[d][v];
        }
        return parent[u];
    };
    vector<int> imosup(N), imosdn(N);
    for(auto [u,v] : B){
        int g = lca(u,v);
        imosup[u] += 1;
        imosup[g] -= 1;
        imosdn[v] += 1;
        imosdn[g] -= 1;
    }
    for(int i=N-1; i>=0; i--){
        int v = ord[i]; int w = parent[v];
        imosup[w] += imosup[v];
        imosdn[w] += imosdn[v];
    }
    //for(auto a : imosup){ cout << a << " "; } cout << endl;
    //for(auto a : imosdn){ cout << a << " "; } cout << endl;
    vector<pair<int,int>> res;
    for(auto [u,v] : A){
        if(u != parent[v]) swap(u,v);
        if(imosup[v] != 0 && imosdn[v] != 0) return {{-1,-1}};
        if(imosup[v] != 0) swap(u,v);
        res.push_back({u,v});
    }
    return res;
}

vector<pair<int,int>> solve(int N, vector<pair<int,int>> A, vector<pair<int,int>> B){
    auto tecc = TECC(N, A);
    auto teccmap = tecc.mapping;
    int M = A.size();
    int n = tecc.treen;
    vector<pair<int,int>> a;
    vector<int> eid;
    rep(e,M){
        auto [u,v] = A[e];
        if(teccmap[u] != teccmap[v]){
            a.emplace_back(teccmap[u], teccmap[v]);
            eid.push_back(e);
        }
    }
    for(auto& [u,v] : B){
        u = teccmap[u];
        v = teccmap[v];
    }
    //for(auto a : teccmap){ cout << a << " "; } cout << endl;
    auto ans = tecc.way;
    auto q = solvetree(n, a, B);
    if(q == vector<pair<int,int>>{{-1,-1}}) return q;
    rep(ei,a.size()){
        auto [u,v] = A[ei];
        if(teccmap[u] != teccmap[ans[eid[ei]].first]){
            swap(ans[eid[ei]].first, ans[eid[ei]].second);
        }
    }
    return ans;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N, M; cin >> N >> M;
    vector<pair<int,int>> graph(M);
    for(auto&[u,v] : graph){ cin >> u >> v; u--; v--; }
    int K; cin >> K;
    vector<pair<int,int>> cons(K);
    for(auto&[u,v] : cons){ cin >> u >> v; u--; v--; }
    auto ans = solve(N, graph, cons);
    if(ans.size() == 1 && ans[0].first == -1){
        cout << "No\n";
    } else {
        cout << "Yes\n";
        for(auto [u,v] : ans) cout << (u+1) << ' ' << (v+1) << '\n';
    }
    return 0;
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 6768
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

vector<vector<int>> G, DG;
vector<bool> seen;
vector<int> ord, low, to, from, dep;
vector<set<int>> U;
int sz = 0;
void LLdfs(int v, int p) {
    ord[v] = sz++;
    low[v] = ord[v];
    bool ch = 0;
    for (int c : G[v]) {
        if (c == p && !ch)ch = 1;
        else if (ord[c] == -1) {
            LLdfs(c, v);
            low[v] = min(low[v], low[c]);
        }
        else low[v] = min(low[v], ord[c]);
    }
}
bool is_bridge(int u, int v) {
    if (ord[u] > ord[v])swap(u, v);
    return ord[u] < low[v];
}
bool OK = 1;
void dfs(int n, int p) {
    if (!OK)return;
    seen[n] = 1;
    for (int v : G[n]) {
        if (v == p)continue;
        if (seen[v]) {
            if (dep[v] > dep[n])DG[v].push_back(n);
        }
        else {
            dep[v] = dep[n] + 1;
            dfs(v, n);
            if (is_bridge(n, v) && min(to[v], from[v]) > 0) {
                OK = 0; return;
            }
            if (!is_bridge(n, v)) {
                DG[n].push_back(v);
            }
            else if (to[v] > 0)DG[v].push_back(n);
            else DG[n].push_back(v);
            
            if (U[v].size() > U[n].size()) {
                swap(U[v], U[n]);
                swap(to[n],to[v]);
                swap(from[n],from[v]);
            }
            for (auto u : U[v]) {
                bool fl = (u>0);
                if (U[n].count(-u)) {
                    U[n].erase(-u);
                    (fl ? from : to)[n]--;
                }
                else {
                    U[n].insert(u);
                    (fl ? to : from)[n]++;
                }
            }
        }
    }
}

int main() {
    ll N, M;
    cin >> N >> M;
    G.resize(N);
    ord.assign(N, -1);
    low.assign(N, -1);
    DG.resize(N);
    for (int i = 0; i < M; i++) {
        int x, y;
        cin >> x >> y;
        x--; y--;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    LLdfs(0, -1);
    to.assign(N, 0);
    from.assign(N, 0);
    U.resize(N);
    seen.assign(N, 0);
    dep.assign(N, 0);
    int k;
    cin >> k;
    for (int i = 0; i < k; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        to[a]++;
        from[b]++;
        U[a].insert(i + 1);
        U[b].insert(-i - 1);
    }
    dfs(0, -1);
    if (OK) {
        cout << "Yes" << endl;
        for (int i = 0; i < N; i++) {
            for (auto v : DG[i])cout << i + 1 << " " << v + 1 << "\n";
        }
    }
    else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 130
memory_kb: 24100
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i64 = long long;
#define var auto
#define int long long

struct LowestCommonAncestor {
  int h; vector<vector<int>> G,par;vector<int> dep;
  LowestCommonAncestor(int n):G(n),dep(n) {
    h = 1;
    while ((1<<h)<=n) h++;
    par.assign(h, vector<int>(n,-1));
  }
  void add_edge(int u, int v) {
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  void dfs(int v, int p, int d) {
    par[0][v]=p;dep[v]=d;
    for(int u:G[v])
      if (u!=p)dfs(u,v,d+1);
  }
  void build(int r=0) {
    int n=G.size();dfs(r,-1,0);
    for (int k = 0; k+1<h;++k)
      for(int v = 0; v<n;++v)
        if (~par[k][v])
          par[k+1][v] = par[k][par[k][v]];
  }
  int lca(int u, int v) {
    if (dep[u]>dep[v])swap(u, v);
    for(int k=0;k<h;++k)
      if((dep[v]-dep[u])>>k&1)
        v=par[k][v];
    if (u==v) return u;
    for (int k=h-1;k>=0;k--)
      if (par[k][u]!=par[k][v])
        u=par[k][u],v=par[k][v];return par[0][u];
  }
};

struct TwoEdgeConnectedComponents {
  vector<int>ord,low,par,blg,sz;vector<vector<int>>G,C;
  TwoEdgeConnectedComponents(int n):
    ord(n,-1),low(n),par(n,-1),blg(n,-1),sz(n,1),G(n){}
  void add_edge(int u,int v) {
    if(u==v)return;
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  bool is_bridge(int u, int v) {
    if(ord[u]>ord[v])swap(u,v);
    return ord[u]<low[v];
  }
  void dfs(int v,int&pos) {
    ord[v]=low[v]=pos++;int dup=0;
    for(int u:G[v]) {
      if(u==par[v]and!dup) {
        dup=1;continue;
      }
      if(~ord[u]) {
        low[v]=min(low[v],ord[u]);continue;
      }
      par[u]=v;dfs(u,pos);sz[v]+=sz[u];
      low[v]=min(low[v],low[u]);
    }
  }
  void fill_component(int v) {
    C[blg[v]].emplace_back(v);
    for(int u:G[v]) {
      if(~blg[u]or is_bridge(u,v))continue;
      blg[u]=blg[v];fill_component(u);
    }
  }
  void add_component(int v,int&k) {
    if(~blg[v])return;
    blg[v]=k++;C.emplace_back();fill_component(v);
  }
  int build() {
    int n=G.size(),pos=0;
    for(int i=0;i<n;++i)
      if(ord[i]<0)dfs(i,pos);
    int k=0;
    for(int i=0;i<n;++i)add_component(i,k);
    return k;
  }
  const vector<int>&operator[](int i)const{return C[i];}
  vector<vector<int>>forest() {
    int n=G.size(),k=C.size();vector<vector<int>>T(k);
    for(int v=0;v<n;++v)
      for(int u:G[v])
        if(blg[v]!=blg[u])
          T[blg[v]].emplace_back(blg[u]);return T;
  }
};

bool flag;

vector<vector<int>> GG;
vector<vector<int>> begin_of;
vector<vector<int>> end_of;

const int DOWN = 1;
const int UP = -1;

map<pair<int, int>, int> dirs;

int sign(int val) {
assert(val != 0);
  return val < 0 ? -1 : 1;
}

set<int> dfs(int s, int from) {
  set<int> st1;

  for (var t : GG[s]) {
    if (from == t) continue;
    set<int> st2 = dfs(t, s);
    // mukiduke
    if (st1.size() < st2.size()) swap(st1, st2);
    st1.merge(st2);
  }

  for (var&& val : end_of[s]) st1.emplace(val);
  for (var&& val : begin_of[s]) st1.erase(val);

  int dir = 1;
  if (st1.size()) {
    if (sign(*st1.begin()) != sign(*st1.rbegin())) {
      flag = false;
    }
    dir = sign(*st1.begin());
  }

  if (from != -1) {
    dirs[make_pair(s, from)] = -dir;
    dirs[make_pair(from, s)] = dir;
  }

  return move(st1); // nennnotame move wo site oku(iranai kedo)
}

#ifdef LOCAL
bool debug = false;
#else
bool debug = false;
#endif

vector<pair<int, int>> solve(int n, int m, int k, vector<pair<int, int>> xys, vector<pair<int, int>> abs) {
  flag = true; dirs.clear();

  vector<pair<int, int>> res;

  TwoEdgeConnectedComponents tecc(n);

  for (var&& [x, y] : xys) {
    tecc.add_edge(x, y);
  }

  tecc.build();
  vector<int> filled(tecc.C.size());
  vector<pair<int, int>> bridges;

  set<pair<int, int>> used_edges;
  vector<int> visited(n, 0);
  for (int i = 0; i < n; i++) {
    if (visited[i]) continue;
    stack<int> st;
    st.emplace(i); visited[i] = 1;
    while(st.size()) {
      var s = st.top(); st.pop();

      for (var t : tecc.G[s]) {
        if (used_edges.count(make_pair(t, s))) continue;
        if (tecc.is_bridge(s, t)) {
          if (s < t) {
            bridges.emplace_back(s, t);
          }
          continue;
        }
        used_edges.emplace(s, t);
        if (visited[t]) {
          res.emplace_back(t, s);
          continue;
        }
        st.emplace(t); visited[t] = 1;
        res.emplace_back(s, t);
      }
    }
  }

  int nn = tecc.C.size();

  GG = vector<vector<int>>(nn);
  LowestCommonAncestor lca(nn);
  for (var&&[s, t]: bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    if (debug) {
      fprintf(stderr, "[+] actual: (%d, %d), remapp: (%d, %d)\n", s, t, ss, tt); fflush(stderr);
    }
    lca.add_edge(ss, tt);
    GG[ss].emplace_back(tt);
    GG[tt].emplace_back(ss);
  }
  lca.build(0);

  begin_of = vector<vector<int>>(nn);
  end_of = vector<vector<int>>(nn);

  int id = 1;
  for (var&&[s, t]: abs) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];

    var l = lca.lca(ss, tt);
    //  l
    // / \
    // s t
    if (ss != l) {
      begin_of[l].emplace_back(-id);
      end_of[ss].emplace_back(-id);
      id++;
    }
    if (l != tt) {
      begin_of[l].emplace_back(id);
      end_of[tt].emplace_back(id);
      id++;
    }
  }

  dfs(0, -1);
  assert(dirs.size() == bridges.size() * 2);

  if (debug) {
    cerr << res.size() << endl;
  }
  for (var&& [s, t] : bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    assert(ss != tt);

    // s to t
    if (dirs[make_pair(ss, tt)] == UP) {
      res.emplace_back(t, s);
    }
    else {
      res.emplace_back(s, t);
    }
  }

  assert(res.size() == m);

  if (!flag) {
    return {};
  }
  return res;
}

vector<bool> checkvisited;
vector<vector<int>> checkG;
bool checkdfs(int s, int from, int tgt) {
  checkvisited[s] = 1;
  if (tgt == s) return true;
  for (var t : checkG[s]) {
    if (checkvisited[t]) continue;
    if (checkdfs(t, s, tgt)) return true;
  }
  return false;
}

bool check(int n, vector<pair<int, int>> res, vector<pair<int, int>> abs) {
  checkG = vector<vector<int>>(n);
  for (var && [s, t] : res) {
    checkG[s].emplace_back(t);
  }
  checkvisited = vector<bool>(n);
  bool f = true;
  for (var&& [a, b] : res) {
    checkvisited = vector<bool>(n);
    if (!checkdfs(a, -1, b)) {
      fprintf(stderr, "[+] unreachable: %d -> %d", a, b);
      f = false;
    }
  }
  return f;
}

void test() {
  for (var i = 0; i < 10000000; i++) {
    if (i % 100 == 0) {
      cout << i << endl << flush;
    }
    srand(i);
    int n = 5;
    int m = rand() % (n * 5) + n;
    int t = rand() % (n * n / 3);
    set<pair<int, int>> s;

    vector<pair<int, int>> xys;
    var add1 = [&](int a, int b) {
      if (a > b) swap(a, b);
      s.emplace(a, b);
      xys.emplace_back(a, b);
    };
    for (int i = 1; i < n; i++) {
      add1(rand() % i, i);
    }

    while (xys.size() < m) {
      int ss, tt;
      do {
        ss = rand() % n;
        tt = rand() % n;
      }while(ss == tt || s.count(make_pair(ss, tt)));
      add1(ss, tt);
    }

    s.clear();
    vector<pair<int, int>> abs;
    while (abs.size() < t) {
      int ss, tt;
      do {
        ss = rand() % n;
        tt = rand() % n;
      }while(ss == tt || s.count(make_pair(ss, tt)));
      s.emplace(ss, tt);
      abs.emplace_back(ss, tt);
    }


    var res = solve(n, m, t, xys, abs);
    if (res.size()) {
      var r = check(n, res, abs);
      assert(r);
    }
  }
}

signed main() {
  cin.tie(0)->sync_with_stdio(false);

  // test();

  int n, m;
  int k;
  cin >> n >> m;
  vector<pair<int, int>> xys(m);
  for (var&& [x, y] : xys) {
    cin >> x >> y; x--; y--;
  }
  cin >> k;
  vector<pair<int, int>> abs(k);
  for (var&& [a, b] : abs) {
    cin >> a >> b; a--; b--;
  }

  var res = solve(n, m, k, xys, abs);

  if (flag) {
    cout << "Yes" << endl;
    for (var&& [s, t] : res) {
      cout << (s + 1) << ' ' << (t + 1) << endl;
    }
  }
  else {
    cout << "No" << endl;
  }
}
accuracy: 0.06060606060606061
time_ms: 50
memory_kb: 14268
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i64 = long long;
#define endl '\n'
#define var auto

struct LowestCommonAncestor {
  int h; vector<vector<int>> G,par;vector<int> dep;
  LowestCommonAncestor(int n):G(n),dep(n) {
    h = 1;
    while ((1<<h)<=n) h++;
    par.assign(h, vector<int>(n,-1));
  }
  void add_edge(int u, int v) {
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  void dfs(int v, int p, int d) {
    par[0][v]=p;dep[v]=d;
    for(int u:G[v])
      if (u!=p)dfs(u,v,d+1);
  }
  void build(int r=0) {
    int n=G.size();dfs(r,-1,0);
    for (int k = 0; k+1<h;++k)
      for(int v = 0; v<n;++v)
        if (~par[k][v])
          par[k+1][v] = par[k][par[k][v]];
  }
  int lca(int u, int v) {
    if (dep[u]>dep[v])swap(u, v);
    for(int k=0;k<h;++k)
      if((dep[v]-dep[u])>>k&1)
        v=par[k][v];
    if (u==v) return u;
    for (int k=h-1;k>=0;k--)
      if (par[k][u]!=par[k][v])
        u=par[k][u],v=par[k][v];return par[0][u];
  }
};

struct TwoEdgeConnectedComponents {
  vector<int>ord,low,par,blg,sz;vector<vector<int>>G,C;
  TwoEdgeConnectedComponents(int n):
    ord(n,-1),low(n),par(n,-1),blg(n,-1),sz(n,1),G(n){}
  void add_edge(int u,int v) {
    if(u==v)return;
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  bool is_bridge(int u, int v) {
    if(ord[u]>ord[v])swap(u,v);
    return ord[u]<low[v];
  }
  void dfs(int v,int&pos) {
    ord[v]=low[v]=pos++;int dup=0;
    for(int u:G[v]) {
      if(u==par[v]and!dup) {
        dup=1;continue;
      }
      if(~ord[u]) {
        low[v]=min(low[v],ord[u]);continue;
      }
      par[u]=v;dfs(u,pos);sz[v]+=sz[u];
      low[v]=min(low[v],low[u]);
    }
  }
  void fill_component(int v) {
    C[blg[v]].emplace_back(v);
    for(int u:G[v]) {
      if(~blg[u]or is_bridge(u,v))continue;
      blg[u]=blg[v];fill_component(u);
    }
  }
  void add_component(int v,int&k) {
    if(~blg[v])return;
    blg[v]=k++;C.emplace_back();fill_component(v);
  }
  int build() {
    int n=G.size(),pos=0;
    for(int i=0;i<n;++i)
      if(ord[i]<0)dfs(i,pos);
    int k=0;
    for(int i=0;i<n;++i)add_component(i,k);
    return k;
  }
  const vector<int>&operator[](int i)const{return C[i];}
  vector<vector<int>>forest() {
    int n=G.size(),k=C.size();vector<vector<int>>T(k);
    for(int v=0;v<n;++v)
      for(int u:G[v])
        if(blg[v]!=blg[u])
          T[blg[v]].emplace_back(blg[u]);return T;
  }
};

bool flag;

vector<vector<int>> GG;
vector<vector<int>> begin_of;
vector<vector<int>> end_of;

const int DOWN = 1;
const int UP = -1;

map<pair<int, int>, int> dirs;

int sign(int val) {
assert(val != 0);
  return val < 0 ? -1 : 1;
}

set<int> dfs(int s, int from) {
  set<int> st1;

  for (var t : GG[s]) {
    if (from == t) continue;
    set<int> st2 = dfs(t, s);
    // mukiduke
    if (st1.size() < st2.size()) swap(st1, st2);
    st1.merge(st2);
  }

  for (var&& val : end_of[s]) st1.emplace(val);
  for (var&& val : begin_of[s]) st1.erase(val);

  int dir = 1;
  if (st1.size()) {
    if (sign(*st1.begin()) != sign(*st1.rbegin())) {
      flag = false;
    }
    dir = sign(*st1.begin());
  }

  if (from != -1) {
    dirs[make_pair(s, from)] = -dir;
    dirs[make_pair(from, s)] = dir;
  }

  return move(st1); // nennnotame move wo site oku(iranai kedo)
}

#ifdef LOCAL
bool debug = false;
#else
bool debug = false;
#endif

vector<pair<int, int>> solve(int n, int m, int k, vector<pair<int, int>> xys, vector<pair<int, int>> abs) {
  flag = true; dirs.clear();

  vector<pair<int, int>> res;

  TwoEdgeConnectedComponents tecc(n);

  for (var&& [x, y] : xys) {
    tecc.add_edge(x, y);
  }

  tecc.build();
  vector<int> filled(tecc.C.size());
  vector<pair<int, int>> bridges;

  set<pair<int, int>> used_edges;
  vector<int> visited(n, 0);
  for (int i = 0; i < n; i++) {
    if (visited[i]) continue;
    stack<int> st;
    st.emplace(i); visited[i] = 1;
    while(st.size()) {
      var s = st.top(); st.pop();

      for (var t : tecc.G[s]) {
        if (used_edges.count(make_pair(t, s))) continue;
        if (tecc.is_bridge(s, t)) {
          if (s < t) {
            bridges.emplace_back(s, t);
          }
          continue;
        }
        used_edges.emplace(s, t);
        if (visited[t]) {
          res.emplace_back(t, s);
          continue;
        }
        st.emplace(t); visited[t] = 1;
        res.emplace_back(s, t);
      }
    }
  }

  int nn = tecc.C.size();

  GG = vector<vector<int>>(nn);
  LowestCommonAncestor lca(nn);
  for (var&&[s, t]: bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    if (debug) {
      fprintf(stderr, "[+] actual: (%d, %d), remapp: (%d, %d)\n", s, t, ss, tt); fflush(stderr);
    }
    lca.add_edge(ss, tt);
    GG[ss].emplace_back(tt);
    GG[tt].emplace_back(ss);
  }
  lca.build(0);

  begin_of = vector<vector<int>>(nn);
  end_of = vector<vector<int>>(nn);

  int id = 1;
  for (var&&[s, t]: abs) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];

    var l = lca.lca(ss, tt);
    //  l
    // / \
    // s t
    if (ss != l) {
      begin_of[l].emplace_back(-id);
      end_of[ss].emplace_back(-id);
      id++;
    }
    if (l != tt) {
      begin_of[l].emplace_back(id);
      end_of[tt].emplace_back(id);
      id++;
    }
  }

  dfs(0, -1);
  assert(dirs.size() == bridges.size() * 2);

  if (debug) {
    cerr << res.size() << endl;
  }
  for (var&& [s, t] : bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    assert(ss != tt);

    // s to t
    if (dirs[make_pair(ss, tt)] == UP) {
      res.emplace_back(t, s);
    }
    else {
      res.emplace_back(s, t);
    }
  }

  assert(res.size() == m);

  if (!flag) {
    return {};
  }
  return res;
}

vector<bool> checkvisited;
vector<vector<int>> checkG;
bool checkdfs(int s, int from, int tgt) {
  checkvisited[s] = 1;
  if (tgt == s) return true;
  for (var t : checkG[s]) {
    if (checkvisited[t]) continue;
    if (checkdfs(t, s, tgt)) return true;
  }
  return false;
}

bool check(int n, vector<pair<int, int>> res, vector<pair<int, int>> abs) {
  checkG = vector<vector<int>>(n);
  for (var && [s, t] : res) {
    checkG[s].emplace_back(t);
  }
  checkvisited = vector<bool>(n);
  bool f = true;
  for (var&& [a, b] : res) {
    checkvisited = vector<bool>(n);
    if (!checkdfs(a, -1, b)) {
      fprintf(stderr, "[+] unreachable: %d -> %d", a, b);
      f = false;
    }
  }
  return f;
}

void test() {
  for (var i = 0; i < 10000000; i++) {
    if (i % 100 == 0) {
      cout << i << endl << flush;
    }
    srand(i);
    int n = 5;
    int m = rand() % (n * 5) + n;
    int t = rand() % (n * n / 3);
    set<pair<int, int>> s;

    vector<pair<int, int>> xys;
    var add1 = [&](int a, int b) {
      if (a > b) swap(a, b);
      s.emplace(a, b);
      xys.emplace_back(a, b);
    };
    for (int i = 1; i < n; i++) {
      add1(rand() % i, i);
    }

    while (xys.size() < m) {
      int ss, tt;
      do {
        ss = rand() % n;
        tt = rand() % n;
      }while(ss == tt || s.count(make_pair(ss, tt)));
      add1(ss, tt);
    }

    s.clear();
    vector<pair<int, int>> abs;
    while (abs.size() < t) {
      int ss, tt;
      do {
        ss = rand() % n;
        tt = rand() % n;
      }while(ss == tt || s.count(make_pair(ss, tt)));
      s.emplace(ss, tt);
      abs.emplace_back(ss, tt);
    }


    var res = solve(n, m, t, xys, abs);
    if (res.size()) {
      var r = check(n, res, abs);
      assert(r);
    }
  }
}

int main() {
  cin.tie(0)->sync_with_stdio(false);

  // test();

  int n, m;
  int k;
  cin >> n >> m;
  vector<pair<int, int>> xys(m);
  for (var&& [x, y] : xys) {
    cin >> x >> y; x--; y--;
  }
  cin >> k;
  vector<pair<int, int>> abs(k);
  for (var&& [a, b] : abs) {
    cin >> a >> b; a--; b--;
  }

  var res = solve(n, m, k, xys, abs);

  if (flag) {
    cout << "Yes" << endl;
    for (var&& [s, t] : res) {
      cout << (s + 1) << ' ' << (t + 1) << endl;
    }
  }
  else {
    cout << "No" << endl;
  }
}
accuracy: 0.06060606060606061
time_ms: 50
memory_kb: 11188
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using i64 = long long;
#define endl '\n'
#define var auto

struct LowestCommonAncestor {
  int h; vector<vector<int>> G,par;vector<int> dep;
  LowestCommonAncestor(int n):G(n),dep(n) {
    h = 1;
    while ((1<<h)<=n) h++;
    par.assign(h, vector<int>(n,-1));
  }
  void add_edge(int u, int v) {
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  void dfs(int v, int p, int d) {
    par[0][v]=p;dep[v]=d;
    for(int u:G[v])
      if (u!=p)dfs(u,v,d+1);
  }
  void build(int r=0) {
    int n=G.size();dfs(r,-1,0);
    for (int k = 0; k+1<h;++k)
      for(int v = 0; v<n;++v)
        if (~par[k][v])
          par[k+1][v] = par[k][par[k][v]];
  }
  int lca(int u, int v) {
    if (dep[u]>dep[v])swap(u, v);
    for(int k=0;k<h;++k)
      if((dep[v]-dep[u])>>k&1)
        v=par[k][v];
    if (u==v) return u;
    for (int k=h-1;k>=0;k--)
      if (par[k][u]!=par[k][v])
        u=par[k][u],v=par[k][v];return par[0][u];
  }
};

struct TwoEdgeConnectedComponents {
  vector<int>ord,low,par,blg,sz;vector<vector<int>>G,C;
  TwoEdgeConnectedComponents(int n):
    ord(n,-1),low(n),par(n,-1),blg(n,-1),sz(n,1),G(n){}
  void add_edge(int u,int v) {
    if(u==v)return;
    G[u].emplace_back(v);G[v].emplace_back(u);
  }
  bool is_bridge(int u, int v) {
    if(ord[u]>ord[v])swap(u,v);
    return ord[u]<low[v];
  }
  void dfs(int v,int&pos) {
    ord[v]=low[v]=pos++;int dup=0;
    for(int u:G[v]) {
      if(u==par[v]and!dup) {
        dup=1;continue;
      }
      if(~ord[u]) {
        low[v]=min(low[v],ord[u]);continue;
      }
      par[u]=v;dfs(u,pos);sz[v]+=sz[u];
      low[v]=min(low[v],low[u]);
    }
  }
  void fill_component(int v) {
    C[blg[v]].emplace_back(v);
    for(int u:G[v]) {
      if(~blg[u]or is_bridge(u,v))continue;
      blg[u]=blg[v];fill_component(u);
    }
  }
  void add_component(int v,int&k) {
    if(~blg[v])return;
    blg[v]=k++;C.emplace_back();fill_component(v);
  }
  int build() {
    int n=G.size(),pos=0;
    for(int i=0;i<n;++i)
      if(ord[i]<0)dfs(i,pos);
    int k=0;
    for(int i=0;i<n;++i)add_component(i,k);
    return k;
  }
  const vector<int>&operator[](int i)const{return C[i];}
  vector<vector<int>>forest() {
    int n=G.size(),k=C.size();vector<vector<int>>T(k);
    for(int v=0;v<n;++v)
      for(int u:G[v])
        if(blg[v]!=blg[u])
          T[blg[v]].emplace_back(blg[u]);return T;
  }
};

bool flag;

vector<vector<int>> GG;
vector<vector<int>> begin_of;
vector<vector<int>> end_of;

const int DOWN = 1;
const int UP = -1;

map<pair<int, int>, int> dirs;

int sign(int val) {
  if (val == 0) return 0;
  return val < 0 ? -1 : 1;
}

set<int> dfs(int s, int from) {
  set<int> st1;

  for (var t : GG[s]) {
    if (from == t) continue;
    set<int> st2 = dfs(t, s);
    // mukiduke
    if (st1.size() < st2.size()) swap(st1, st2);
    st1.merge(st2);
  }

  for (var&& val : end_of[s]) st1.emplace(val);
  for (var&& val : begin_of[s]) st1.erase(val);

  int dir = 1;
  if (st1.size()) {
    if (sign(*st1.begin()) != sign(*st1.rbegin())) {
      flag = false;
    }
    dir = sign(*st1.begin());
  }

  if (from != -1) {
    dirs[make_pair(s, from)] = -dir;
    dirs[make_pair(from, s)] = dir;
  }

  return move(st1); // nennnotame move wo site oku(iranai kedo)
}

#ifdef LOCAL
bool debug = true;
#else
bool debug = false;
#endif

vector<pair<int, int>> solve(int n, int m, int k, vector<pair<int, int>> xys, vector<pair<int, int>> abs) {
  flag = true; dirs.clear();

  vector<pair<int, int>> res;

  TwoEdgeConnectedComponents tecc(n);

  for (var&& [x, y] : xys) {
    tecc.add_edge(x, y);
  }

  tecc.build();
  vector<int> filled(tecc.C.size());
  vector<pair<int, int>> bridges;

  set<pair<int, int>> used_edges;
  vector<int> visited(n, 0);
  for (int i = 0; i < n; i++) {
    if (visited[i]) continue;
    stack<int> st;
    st.emplace(i); visited[i] = 1;
    while(st.size()) {
      var s = st.top(); st.pop();

      for (var t : tecc.G[s]) {
        if (used_edges.count(make_pair(t, s))) continue;
        if (tecc.is_bridge(s, t)) {
          if (s < t) {
            bridges.emplace_back(s, t);
          }
          continue;
        }
        used_edges.emplace(s, t);
        if (visited[t]) {
          res.emplace_back(t, s);
          continue;
        }
        st.emplace(t); visited[t] = 1;
        res.emplace_back(s, t);
      }
    }
  }

  int nn = tecc.C.size();

  GG = vector<vector<int>>(nn);
  LowestCommonAncestor lca(nn);
  for (var&&[s, t]: bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    if (debug) {
      fprintf(stderr, "[+] actual: (%d, %d), remapp: (%d, %d)\n", s, t, ss, tt); fflush(stderr);
    }
    lca.add_edge(ss, tt);
    GG[ss].emplace_back(tt);
    GG[tt].emplace_back(ss);
  }
  lca.build(0);

  begin_of = vector<vector<int>>(nn);
  end_of = vector<vector<int>>(nn);

  int id = 1;
  for (var&&[s, t]: abs) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];

    var l = lca.lca(ss, tt);
    //  l
    // / \
    // s t
    if (ss != l) {
      begin_of[l].emplace_back(-id);
      end_of[ss].emplace_back(-id);
      id++;
    }
    if (l != tt) {
      begin_of[l].emplace_back(id);
      end_of[tt].emplace_back(id);
      id++;
    }
  }

  dfs(0, -1);
  assert(dirs.size() == bridges.size() * 2);

  if (debug) {
    cerr << res.size() << endl;
  }
  for (var&& [s, t] : bridges) {
    var ss = tecc.blg[s];
    var tt = tecc.blg[t];
    assert(ss != tt);

    // s to t
    if (dirs[make_pair(ss, tt)] == UP) {
      res.emplace_back(t, s);
    }
    else {
      res.emplace_back(s, t);
    }
  }

  assert(res.size() == m);

  if (!flag) {
    return {};
  }
  return res;
}

int main() {
  cin.tie(0)->sync_with_stdio(false);
  int n, m;
  int k;
  cin >> n >> m;
  vector<pair<int, int>> xys(m);
  for (var&& [x, y] : xys) {
    cin >> x >> y; x--; y--;
  }
  cin >> k;
  vector<pair<int, int>> abs(k);
  for (var&& [a, b] : abs) {
    cin >> a >> b; a--; b--;
  }

  var res = solve(n, m, k, xys, abs);

  if (flag) {
    cout << "Yes" << endl;
    for (var&& [s, t] : res) {
      cout << (s + 1) << ' ' << (t + 1) << endl;
    }
  }
  else {
    cout << "No" << endl;
  }
}
accuracy: 0.06060606060606061
time_ms: 50
memory_kb: 11300
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct LowLink{
    const int n; vector<vector<int>> g;
    vector<int> used,ord,low,id,arti,par;
    LowLink(const int& _n=0):n(_n),g(n),
        used(n,0),ord(n,0),low(n,0),id(n,-1),par(n,-1){
    }
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
     }
    void dfs(int v,int p,int& k){
        used[v]=1; low[v]=ord[v]=k++;
        par[v] = p;
        bool isarti=0;
        int cnt=0,sub=0;
        for(auto& to:g[v]){
            if(to==p and (++sub)<=1)continue;
            if(!used[to]){
                cnt++; dfs(to,v,k);
                chmin(low[v],low[to]);
                isarti|=(p>=0&&low[to]>=ord[v]);
            }
            else chmin(low[v],ord[to]);
        }
        isarti|=(p==-1&&cnt>1);
        if(isarti)arti.push_back(v);
    }
    void dfs2(int v,int p,int& k){
        if(p!=-1 and ord[p]>=low[v])id[v]=id[p];
        else id[v]=k++;
        for(auto& to:g[v])if(id[to]==-1)dfs2(to,v,k);
    }
    int run(){
        int k=0; rep(i,0,n)if(!used[i])dfs(i,-1,k);
        k=0; rep(i,0,n)if(id[i]==-1)dfs2(i,-1,k);
        return k;
    }
};

/**
 * @brief Lowlink
 */

struct HLD{
    using P=pair<int,int>;
    vector<vector<int>> g; vector<int> sz,in,out,rev,hs,par,dist;
    void dfs(int v,int p){
        par[v]=p; sz[v]=1;
        if(p!=-1)dist[v]=dist[p]+1;
        if(!g[v].empty() and g[v][0]==p)swap(g[v][0],g[v].back());
        for(auto& to:g[v])if(to!=p){
           dfs(to,v); sz[v]+=sz[to];
           if(sz[g[v][0]]<sz[to])swap(g[v][0],to);
        }
    }
    void dfs2(int v,int p,int& k){
        in[v]=k++; rev[in[v]]=v;
        for(auto& to:g[v])if(to!=p){
            hs[to]=(g[v][0]==to?hs[v]:to);
            dfs2(to,v,k);
        }
        out[v]=k;
    }
    HLD(int _n):g(_n),sz(_n),in(_n),out(_n),rev(_n),hs(_n),par(_n),dist(_n){}
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
    }
    void run(int rt=0){
        dfs(rt,-1);
        hs[rt]=rt;
        int k=0;
        dfs2(rt,-1,k);
    }
    int lca(int u,int v){
        for(;;v=par[hs[v]]){
            if(in[u]>in[v])swap(u,v);
            if(hs[u]==hs[v])return u;
        }
    }
    vector<P> get(int u,int p,bool es=0){
        assert(in[p]<=in[u] and out[u]<=out[p]);
        vector<P> res;
        while(hs[u]!=hs[p]){
            res.push_back({in[hs[u]],in[u]+1});
            u=par[hs[u]];
        }
        res.push_back({in[p]+es,in[u]+1});
        return res;
    }
    int jump(int u,int v,int k){
        if(k<0)return -1;
        int g=lca(u,v);
        int d0=dist[u]+dist[v]-dist[g]*2;
        if(d0<k)return -1;
        int st=u;
        if(dist[u]-dist[g]<k)st=v,k=d0-k;
        for(;;){
            int to=hs[st];
            if(in[st]-k>=in[to])return rev[in[st]-k];
            k-=in[st]-in[to]+1; st=par[to];
        }
    }
};

/**
 * @brief Heavy Light Decomposition
 */

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    vector<int> A(M), B(M);
    LowLink G(N);
    rep(i,0,M) {
        cin >> A[i] >> B[i];
        A[i]--, B[i]--;
        G.add_edge(A[i],B[i]);
    }
    int lows = G.run();
    vector<vector<int>> H(lows);
    HLD HL(lows);
    rep(i,0,M) {
        if (G.id[A[i]] != G.id[B[i]]) {
            HL.add_edge(G.id[A[i]], G.id[B[i]]);
            H[G.id[A[i]]].push_back(G.id[B[i]]);
            H[G.id[B[i]]].push_back(G.id[A[i]]);
        }
    }
    HL.run();
    vector<int> ImosUp(N,0), ImosDown(N,0);
    int Q;
    cin >> Q;
    while(Q--) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        if (G.id[a] == G.id[b]) continue;
        int From = G.id[a], To = G.id[b];
        int L = HL.lca(From, To);
        ImosUp[From]++, ImosUp[L]--;
        ImosDown[To]++, ImosDown[L]--;
    }
    auto ImosCalc = [&](auto self, vector<int>& imos, int V, int P) -> void {
        for (int NV : H[V]) {
            if (NV == P) continue;
            self(self, imos, NV, V);
            imos[V] += imos[NV];
        }
    };
    ImosCalc(ImosCalc, ImosUp, 0, -1);
    ImosCalc(ImosCalc, ImosDown, 0, -1);
    rep(i,0,lows) {
        if (ImosUp[i] > 0 && ImosDown[i] > 0) {
            cout << "No" << endl;
            return 0;
        }
    }
    cout << "Yes" << endl;
    rep(i,0,M) {
        int a = A[i], b = B[i];
        int la = G.id[a], lb = G.id[b];
        if (la == lb) {
            int oa = G.ord[a], ob = G.ord[b];
            if (oa < ob) {
                if (G.par[b] == a) cout << a+1 << ' ' << b+1 << endl;
                else cout << b+1 << ' ' << a+1 << endl;
            }
            else {
                if (G.par[a] == b) cout << b+1 << ' ' << a+1 << endl;
                else cout << a+1 << ' ' << b+1 << endl;
            }
        }
        else {
            int ll = HL.lca(la, lb);
            if (ll == la) {
                if (ImosUp[lb] > 0) cout << b+1 << ' ' << a+1 << endl;
                else cout << a+1 << ' ' << b+1 << endl;
            }
            else {
                if (ImosUp[la] > 0) cout << a+1 << ' ' << b+1 << endl;
                else cout << b+1 << ' ' << a+1 << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 80
memory_kb: 6244
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct LowLink{
    const int n; vector<vector<int>> g;
    vector<int> used,ord,low,id,arti;
    LowLink(const int& _n=0):n(_n),g(n),
        used(n,0),ord(n,0),low(n,0),id(n,-1){
    }
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
     }
    void dfs(int v,int p,int& k){
        used[v]=1; low[v]=ord[v]=k++;
        bool isarti=0;
        int cnt=0,sub=0;
        for(auto& to:g[v]){
            if(to==p and (++sub)<=1)continue;
            if(!used[to]){
                cnt++; dfs(to,v,k);
                chmin(low[v],low[to]);
                isarti|=(p>=0&&low[to]>=ord[v]);
            }
            else chmin(low[v],ord[to]);
        }
        isarti|=(p==-1&&cnt>1);
        if(isarti)arti.push_back(v);
    }
    void dfs2(int v,int p,int& k){
        if(p!=-1 and ord[p]>=low[v])id[v]=id[p];
        else id[v]=k++;
        for(auto& to:g[v])if(id[to]==-1)dfs2(to,v,k);
    }
    int run(){
        int k=0; rep(i,0,n)if(!used[i])dfs(i,-1,k);
        k=0; rep(i,0,n)if(id[i]==-1)dfs2(i,-1,k);
        return k;
    }
};

/**
 * @brief Lowlink
 */

struct HLD{
    using P=pair<int,int>;
    vector<vector<int>> g; vector<int> sz,in,out,rev,hs,par,dist;
    void dfs(int v,int p){
        par[v]=p; sz[v]=1;
        if(p!=-1)dist[v]=dist[p]+1;
        if(!g[v].empty() and g[v][0]==p)swap(g[v][0],g[v].back());
        for(auto& to:g[v])if(to!=p){
           dfs(to,v); sz[v]+=sz[to];
           if(sz[g[v][0]]<sz[to])swap(g[v][0],to);
        }
    }
    void dfs2(int v,int p,int& k){
        in[v]=k++; rev[in[v]]=v;
        for(auto& to:g[v])if(to!=p){
            hs[to]=(g[v][0]==to?hs[v]:to);
            dfs2(to,v,k);
        }
        out[v]=k;
    }
    HLD(int _n):g(_n),sz(_n),in(_n),out(_n),rev(_n),hs(_n),par(_n),dist(_n){}
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
    }
    void run(int rt=0){
        dfs(rt,-1);
        hs[rt]=rt;
        int k=0;
        dfs2(rt,-1,k);
    }
    int lca(int u,int v){
        for(;;v=par[hs[v]]){
            if(in[u]>in[v])swap(u,v);
            if(hs[u]==hs[v])return u;
        }
    }
    vector<P> get(int u,int p,bool es=0){
        assert(in[p]<=in[u] and out[u]<=out[p]);
        vector<P> res;
        while(hs[u]!=hs[p]){
            res.push_back({in[hs[u]],in[u]+1});
            u=par[hs[u]];
        }
        res.push_back({in[p]+es,in[u]+1});
        return res;
    }
    int jump(int u,int v,int k){
        if(k<0)return -1;
        int g=lca(u,v);
        int d0=dist[u]+dist[v]-dist[g]*2;
        if(d0<k)return -1;
        int st=u;
        if(dist[u]-dist[g]<k)st=v,k=d0-k;
        for(;;){
            int to=hs[st];
            if(in[st]-k>=in[to])return rev[in[st]-k];
            k-=in[st]-in[to]+1; st=par[to];
        }
    }
};

/**
 * @brief Heavy Light Decomposition
 */

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    vector<int> A(M), B(M);
    LowLink G(N);
    rep(i,0,M) {
        cin >> A[i] >> B[i];
        A[i]--, B[i]--;
        G.add_edge(A[i],B[i]);
    }
    int lows = G.run();
    vector<vector<int>> H(lows);
    HLD HL(lows);
    rep(i,0,M) {
        if (G.id[A[i]] != G.id[B[i]]) {
            HL.add_edge(G.id[A[i]], G.id[B[i]]);
            H[G.id[A[i]]].push_back(G.id[B[i]]);
            H[G.id[B[i]]].push_back(G.id[A[i]]);
        }
    }
    HL.run();
    vector<int> ImosUp(N,0), ImosDown(N,0);
    int Q;
    cin >> Q;
    while(Q--) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        if (G.id[a] == G.id[b]) continue;
        int From = G.id[a], To = G.id[b];
        int L = HL.lca(From, To);
        ImosUp[From]++, ImosUp[L]--;
        ImosDown[To]++, ImosDown[L]--;
    }
    vector<int> Par(lows,-1);
    auto ImosCalc = [&](auto self, vector<int>& imos, int V, int P) -> void {
        Par[V] = P;
        for (int NV : H[V]) {
            if (NV == P) continue;
            self(self, imos, NV, V);
            imos[V] += imos[NV];
        }
    };
    ImosCalc(ImosCalc, ImosUp, 0, -1);
    ImosCalc(ImosCalc, ImosDown, 0, -1);
    rep(i,0,lows) {
        if (ImosUp[i] > 0 && ImosDown[i] > 0) {
            cout << "No" << endl;
            return 0;
        }
    }
    cout << "Yes" << endl;
    rep(i,0,M) {
        int a = A[i], b = B[i];
        int la = G.id[a], lb = G.id[b];
        if (la == lb) {
            int oa = G.ord[a], ob = G.ord[b];
            if (oa < ob) {
                if (Par[lb] == la) cout << a+1 << ' ' << b+1 << endl;
                else cout << b+1 << ' ' << a+1 << endl;
            }
            else {
                if (Par[la] == lb) cout << b+1 << ' ' << a+1 << endl;
                else cout << a+1 << ' ' << b+1 << endl;
            }
        }
        else {
            int ll = HL.lca(la, lb);
            if (ll == la) {
                if (ImosUp[lb] > 0) cout << b+1 << ' ' << a+1 << endl;
                else cout << a+1 << ' ' << b+1 << endl;
            }
            else {
                if (ImosUp[la] > 0) cout << a+1 << ' ' << b+1 << endl;
                else cout << b+1 << ' ' << a+1 << endl;
            }
        }
    }
}
accuracy: 0.06060606060606061
time_ms: 10
memory_kb: 5288
final_rank: 11