#include <bits/stdc++.h>
using namespace std;
using namespace rel_ops;
using ll = int64_t;
using Pii = pair<int, int>;
using ull = uint64_t;
using Vi = vector<int>;
void run();
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(10);
  run();
  return 0;
}
int uplg(int n) { return 32 - __builtin_clz(n); }
int uplg(ll n) { return 64 - __builtin_clzll(n); }
struct Treap {
  struct Node {
    int E[2] = {-1, -1}, weight{rand()};
    int size{1}, par{-1};
    bool flip{false};
  };
  vector<Node> G;
  Treap(int n = 0) { init(n); }
  void init(int n) {
    G.clear();
    G.resize(n);
  }
  int size(int first) { return (first >= 0 ? G[first].size : 0); }
  void push(int first) {
    if (first >= 0 && G[first].flip) {
      G[first].flip = 0;
      swap(G[first].E[0], G[first].E[1]);
      for (auto& e : (G[first].E))
        if (e >= 0) G[e].flip ^= 1;
    }
  }
  void update(int first) {
    if (first >= 0) {
      G[first].par = -1;
      int& s = G[first].size = 1;
      for (auto& e : (G[first].E))
        if (e >= 0) {
          s += size(e);
          G[e].par = first;
        }
    }
  }
  void split(int first, int& l, int& r, int i) {
    push(first);
    l = r = -1;
    if (first < 0) return;
    int key = size(G[first].E[0]);
    if (i <= key) {
      split(G[first].E[0], l, G[first].E[0], i);
      r = first;
    } else {
      split(G[first].E[1], G[first].E[1], r, i - key - 1);
      l = first;
    }
    update(first);
  }
  int join(int l, int r) {
    push(l);
    push(r);
    if (l < 0 || r < 0) return max(l, r);
    if (G[l].weight < G[r].weight) {
      G[l].E[1] = join(G[l].E[1], r);
      update(l);
      return l;
    }
    G[r].E[0] = join(l, G[r].E[0]);
    update(r);
    return r;
  }
  int find(int first, int i) {
    while (first >= 0) {
      push(first);
      int key = size(G[first].E[0]);
      if (key == i) return first;
      first = G[first].E[key < i];
      if (key < i) i -= key + 1;
    }
    return first;
  }
  int reverse(int first, int l, int r) {
    int a, b, c;
    split(first, b, c, r);
    split(b, a, b, l);
    if (b >= 0) G[b].flip ^= 1;
    return join(join(a, b), c);
  }
  int index(int first) {
    int prev = -2, i = 0;
    while (first != -1) {
      if (G[first].E[0] != prev) i += size(G[first].E[0]) + 1;
      prev = first;
      first = G[first].par;
    }
    return i - 1;
  }
};
struct Vert {
  Vi E, back;
  int state{0}, par{-1}, post{-1}, in{0}, out{0}, depth{0};
  bool inTopo{false};
  ;
};
int n, m, s, t, post;
vector<Vert> G;
vector<Pii> ans;
Treap topo;
int topoRoot;
vector<Pii> suspended;
bool somethingChanged;
void dfs(int i) {
  G[i].state = 1;
  for (auto& e : (G[i].E))
    if (e != G[i].par) {
      if (G[e].state) {
        if (G[e].state == 1) G[e].back.push_back(i);
      } else {
        G[e].par = i;
        G[e].depth = G[i].depth + 1;
        dfs(e);
      }
    }
  G[i].state = 2;
}
void setEdge(int i, int j, bool rev) {
  if (rev) swap(i, j);
  if (G[i].inTopo && G[j].inTopo) return;
  if (G[i].inTopo) {
    int L, R, ind = topo.index(i);
    topo.split(topoRoot, L, R, ind + 1);
    L = topo.join(L, j);
    topoRoot = topo.join(L, R);
    G[j].inTopo = 1;
  } else if (G[j].inTopo) {
    int L, R, ind = topo.index(j);
    topo.split(topoRoot, L, R, ind);
    L = topo.join(L, i);
    topoRoot = topo.join(L, R);
    G[i].inTopo = 1;
  } else {
    assert(0);
  }
}
int findUsed(int i) {
  if (G[i].state > 2) return i;
  return findUsed(G[i].par);
}
void direct(int i, bool reverse);
void addArc(int i, int e) {
  if (G[e].state == 2) {
    int used = findUsed(e);
    if (i == used) {
      suspended.push_back({i, e});
      return;
    }
    bool flag = (topo.index(i) < topo.index(used));
    setEdge(e, i, flag);
    direct(e, flag);
  }
}
void direct(int i, bool reverse) {
  if (G[i].state > 2) return;
  G[i].state = 3;
  somethingChanged = 1;
  if (G[i].par >= 0) {
    setEdge(G[i].par, i, reverse);
    direct(G[i].par, reverse);
  }
  for (auto& e : (G[i].back)) addArc(i, e);
  G[i].state = 4;
}
bool solve() {
  cin >> n >> m >> s >> t;
  s--;
  t--;
  G.assign(n, {});
  suspended.clear();
  ans.clear();
  topo.init(n);
  topoRoot = t;
  G[t].inTopo = 1;
  somethingChanged = 0;
  for (int i = (0); i < (m); i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    G[a].E.push_back(b);
    G[b].E.push_back(a);
  }
  dfs(s);
  if (G[t].state == 0) return false;
  for (auto& v : (G)) {
    sort((v.back).begin(), (v.back).end(),
         [](int l, int r) { return G[l].depth > G[r].depth; });
  }
  for (int i = (0); i < (n); i++)
    ;
  direct(t, false);
  while (somethingChanged) {
    somethingChanged = 0;
    vector<Pii> vec;
    vec.swap(suspended);
    for (auto& p : (vec)) addArc(p.first, p.second);
  }
  for (int i = (0); i < (n); i++) {
    for (auto& e : (G[i].E)) {
      if (topo.index(i) < topo.index(e)) {
        ans.push_back({i, e});
        G[i].out++;
        G[e].in++;
      }
    }
  }
  if (G[s].in != 0 || G[t].out != 0) return false;
  for (int i = (0); i < (n); i++)
    if (i != s && i != t) {
      if (G[i].in == 0 || G[i].out == 0) return false;
    }
  return true;
}
void readTest(bool print) {
  cin >> n >> m >> s >> t;
  if (print) cout << n << ' ' << m << ' ' << s << ' ' << t << '\n';
  for (int i = (0); i < (m); i++) {
    int a, b;
    cin >> a >> b;
    if (print) cout << a << ' ' << b << '\n';
  }
}
void run() {
  int k;
  cin >> k;
  while (k--) {
    if (solve()) {
      cout << "Yes\n";
      for (auto& p : (ans)) cout << p.first + 1 << ' ' << p.second + 1 << '\n';
    } else {
      cout << "No\n";
    }
  }
}
