#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cerr << fixed << setprecision(10);
  }
} iosetup;
using CostType = long long;
struct Edge {
  int src, dst;
  CostType cost;
  Edge(int src, int dst, CostType cost = 0) : src(src), dst(dst), cost(cost) {}
  inline bool operator<(const Edge &rhs) const {
    return cost != rhs.cost ? cost < rhs.cost
           : dst != rhs.dst ? dst < rhs.dst
                            : src < rhs.src;
  }
  inline bool operator<=(const Edge &rhs) const { return !(rhs < *this); }
  inline bool operator>(const Edge &rhs) const { return rhs < *this; }
  inline bool operator>=(const Edge &rhs) const { return !(*this < rhs); }
};
struct Lowlink {
  vector<int> ap;
  vector<Edge> bridge;
  Lowlink(const vector<vector<Edge> > &graph) : graph(graph) {
    int n = graph.size();
    order.assign(n, -1);
    lowlink.resize(n);
    int tm = 0;
    for (int i = (0); i < (n); ++i) {
      if (order[i] == -1) dfs(-1, i, tm);
    }
  }

 private:
  vector<vector<Edge> > graph;
  vector<int> order, lowlink;
  void dfs(int par, int ver, int &tm) {
    order[ver] = lowlink[ver] = tm++;
    int cnt = 0;
    bool is_ap = false;
    for (const Edge &e : graph[ver]) {
      if (order[e.dst] == -1) {
        ++cnt;
        dfs(ver, e.dst, tm);
        lowlink[ver] = min(lowlink[ver], lowlink[e.dst]);
        if (order[ver] <= lowlink[e.dst]) {
          is_ap = true;
          if (order[ver] < lowlink[e.dst])
            bridge.emplace_back(min(ver, e.dst), max(ver, e.dst), e.cost);
        }
      } else if (e.dst != par) {
        lowlink[ver] = min(lowlink[ver], order[e.dst]);
      }
    }
    if (par == -1) {
      if (cnt >= 2) ap.emplace_back(ver);
    } else {
      if (is_ap) ap.emplace_back(ver);
    }
  }
};
struct UnionFind {
  UnionFind(int n) : data(n, -1) {}
  int root(int ver) {
    return data[ver] < 0 ? ver : data[ver] = root(data[ver]);
  }
  void unite(int ver1, int ver2) {
    ver1 = root(ver1);
    ver2 = root(ver2);
    if (ver1 != ver2) {
      if (data[ver1] > data[ver2]) swap(ver1, ver2);
      data[ver1] += data[ver2];
      data[ver2] = ver1;
    }
  }
  bool same(int ver1, int ver2) { return root(ver1) == root(ver2); }
  int size(int ver) { return -data[root(ver)]; }

 private:
  vector<int> data;
};
int main() {
  int t;
  cin >> t;
  while (t--) {
    int n, m, a, b;
    cin >> n >> m >> a >> b;
    --a;
    --b;
    if (a > b) swap(a, b);
    UnionFind uf(n);
    vector<int> a_edge, b_edge;
    while (m--) {
      int u, v;
      cin >> u >> v;
      --u;
      --v;
      if (u > v) swap(u, v);
      if (u == a || v == a) {
        if (v == b) continue;
        a_edge.emplace_back(u == a ? v : u);
      } else if (u == b || v == b) {
        b_edge.emplace_back(u == b ? v : u);
      } else {
        uf.unite(u, v);
      }
    }
    vector<long long> cnt(n, 0);
    for (int i = (0); i < (n); ++i) {
      if (i == a || i == b) continue;
      ++cnt[uf.root(i)];
    }
    long long ans = 0;
    for (int i = (0); i < (n); ++i) ans += cnt[i] * (cnt[i] - 1) / 2;
    for (int &e : a_edge) e = uf.root(e);
    sort((a_edge).begin(), (a_edge).end());
    a_edge.erase(unique((a_edge).begin(), (a_edge).end()), a_edge.end());
    for (int &e : b_edge) e = uf.root(e);
    sort((b_edge).begin(), (b_edge).end());
    b_edge.erase(unique((b_edge).begin(), (b_edge).end()), b_edge.end());
    vector<bool> boolean(n, false);
    vector<int> sz;
    for (int e : a_edge) {
      boolean[e] = true;
      sz.emplace_back(uf.size(e));
    }
    long long sum = accumulate((sz).begin(), (sz).end(), 0LL);
    for (int e : sz) {
      sum -= e;
      ans += sum * e;
    }
    sz.clear();
    long long tokubetsu = 0;
    for (int e : b_edge) {
      if (boolean[e]) {
        tokubetsu += uf.size(e);
      } else {
        sz.emplace_back(uf.size(e));
      }
    }
    sz.emplace_back(tokubetsu);
    sum = accumulate((sz).begin(), (sz).end(), 0LL);
    for (int e : sz) {
      sum -= e;
      ans += sum * e;
    }
    cout << 1LL * (n - 2) * (n - 3) / 2 - ans << '\n';
  }
  return 0;
}
