#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const long long INF = (1 << 30) - 1;
const long long LLINF = (1LL << 60LL);
const long long MOD = 1000000007;
const long long mod = 998244353;
const long long MAX = 1100000;
const double pi = acos(-1);
const double eps = 1e-10;
long long dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
struct Timer {
  chrono::system_clock::time_point start, end;
  Timer() { start = chrono::system_clock::now(); }
  ~Timer() {
    end = chrono::system_clock::now();
    auto msec =
        chrono::duration_cast<chrono::milliseconds>(end - start).count();
    cerr << "time : " << msec << " ms" << endl;
  }
};
struct UnionFind {
  vector<long long> par;
  UnionFind(long long n) : par(n, -1) {}
  void init(long long n) { par.assign(n, -1); }
  long long find(long long x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = find(par[x]);
  }
  bool same(long long x, long long y) { return find(x) == find(y); }
  bool unite(long long x, long long y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;
    if (par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }
  long long size(long long x) { return -par[find(x)]; }
  void print(long long x) {
    for (long long i = 0; i < x; i++) {
      cout << par[i] << endl;
    }
    return;
  }
};
signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(15);
  Timer TM;
  long long t;
  cin >> t;
  for (long long T = 0; T < t; T++) {
    long long n, m, a, b;
    cin >> n >> m >> a >> b;
    a--;
    b--;
    if (a > b) swap(a, b);
    vector<long long> G[n];
    UnionFind uf(n);
    for (long long i = 0; i < m; i++) {
      long long s, t;
      cin >> s >> t;
      s--;
      t--;
      if (s > t) swap(s, t);
      if (s == a && t == b) {
        G[s].push_back(t);
        G[t].push_back(s);
      } else if (s == a || s == b) {
        G[s].push_back(uf.find(t));
        G[uf.find(t)].push_back(s);
      } else if (t == b || t == a) {
        G[uf.find(s)].push_back(t);
        G[t].push_back(uf.find(s));
      } else {
        uf.unite(s, t);
      }
    }
    sort(G[a].begin(), G[a].end());
    sort(G[b].begin(), G[b].end());
    sort(G[a].begin(), G[a].end());
    G[a].erase(unique(G[a].begin(), G[a].end()), G[a].end());
    sort(G[b].begin(), G[b].end());
    G[b].erase(unique(G[b].begin(), G[b].end()), G[b].end());
    map<long long, long long> mp;
    long long x = 0, y = 0;
    for (long long i : G[a]) {
      i = uf.find(i);
      if (i == b) continue;
      mp[i]++;
      x += uf.size(i);
    }
    for (long long i : G[b]) {
      i = uf.find(i);
      if (i == a) continue;
      if (mp[i] > 0) {
        x -= uf.size(i);
      } else
        y += uf.size(i);
    }
    cout << x * y << endl;
  }
  return 0;
}
