#include <bits/stdc++.h>
using namespace std;
class bcc {
 public:
  int n;
  vector<int> vis, depth, min_depth, pre, order;
  bcc(int _n) : n(_n) {
    vis.resize(n);
    depth.resize(n);
    min_depth.resize(n);
    pre.resize(n, -1);
  }
  void dfs_all(vector<vector<int>> &graph) {
    fill(vis.begin(), vis.end(), 0);
    fill(depth.begin(), depth.end(), 0);
    fill(min_depth.begin(), min_depth.end(), 0);
    fill(pre.begin(), pre.end(), -1);
    int cnt = 0;
    function<void(int)> dfs = [&](int u) {
      order.push_back(u);
      vis[u] = cnt;
      min_depth[u] = depth[u];
      for (int v : graph[u]) {
        if (v == pre[u]) continue;
        if (vis[v] == cnt) {
          min_depth[u] = min(min_depth[u], depth[v]);
          continue;
        }
        depth[v] = depth[u] + 1;
        pre[v] = u;
        dfs(v);
        min_depth[u] = min(min_depth[u], min_depth[v]);
      }
    };
    for (int u = 0; u < n; u++) {
      if (vis[u]) continue;
      cnt++;
      dfs(u);
    }
  }
  int find_edge_bcc(vector<vector<int>> &graph, vector<int> &comp) {
    dfs_all(graph);
    int res = 0;
    for (int u : order) {
      if (pre[u] == -1 || min_depth[u] == depth[u]) {
        comp[u] = res++;
      } else {
        comp[u] = comp[pre[u]];
      }
    }
    return res;
  }
  int find_bridge(vector<vector<int>> &graph, vector<pair<int, int>> &bridges) {
    dfs_all(graph);
    for (int u = 0; u < n; u++) {
      if (pre[u] != -1 && min_depth[u] == depth[u]) {
        bridges.emplace_back(u, pre[u]);
      }
    }
    return (int)bridges.size();
  }
  int find_vertex_bcc(vector<vector<int>> &graph, vector<int> &comp) {
    dfs_all(graph);
    int res = 0;
    for (int u : order) {
      if (pre[u] == -1) {
        comp[u] = -1;
        continue;
      }
      if (min_depth[u] >= depth[pre[u]]) {
        comp[u] = res++;
      } else {
        comp[u] = comp[pre[u]];
      }
    }
    return res;
  }
  int find_cutvertex(vector<vector<int>> &graph, vector<int> &cutvertexs) {
    dfs_all(graph);
    vector<bool> iscut(n);
    for (int u = 0; u < n; u++) {
      if (pre[u] != -1 && min_depth[u] >= depth[pre[u]]) {
        iscut[u] = true;
      }
    }
    vector<int> children(n);
    for (int u = 0; u < n; u++) {
      if (pre[u] != -1) {
        children[pre[u]]++;
      }
    }
    for (int u = 0; u < n; u++) {
      if (pre[u] == -1) {
        iscut[u] = children[u] > 1;
      };
    }
    for (int u = 0; u < n; u++) {
      if (iscut[u]) {
        cutvertexs.push_back(u);
      }
    }
    return (int)cutvertexs.size();
  }
};
class lca {
 public:
  int n, logn;
  vector<vector<int>> parent;
  vector<int> depth;
  lca(vector<vector<int>> &tree, int rt = 0) {
    n = (int)tree.size(), logn = log2(n) + 1;
    parent.resize(n, vector<int>(logn));
    depth.resize(n);
    function<void(int, int, int)> dfs = [&](int u, int p, int d) {
      parent[u][0] = p;
      depth[u] = d;
      for (int v : tree[u]) {
        if (v == p) continue;
        dfs(v, u, d + 1);
      }
    };
    dfs(rt, -1, 0);
    for (int k = 0; k + 1 < logn; k++) {
      for (int u = 0; u < n; u++) {
        if (parent[u][k] < 0) {
          parent[u][k + 1] = -1;
        } else {
          parent[u][k + 1] = parent[parent[u][k]][k];
        }
      }
    }
  }
  int get(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < logn; k++) {
      if ((depth[v] - depth[u]) >> k & 1) {
        v = parent[v][k];
      }
    }
    if (u == v) return u;
    for (int k = logn - 1; k >= 0; k--) {
      if (parent[u][k] != parent[v][k]) {
        u = parent[u][k];
        v = parent[v][k];
      }
    }
    return parent[u][0];
  }
  int log2(int b) { return 31 - __builtin_clz(b); }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int t;
  cin >> t;
  while (t--) {
    int n, m, a, b;
    cin >> n >> m >> a >> b;
    a--;
    b--;
    vector<vector<int>> graph(n);
    vector<pair<int, int>> edges(m);
    for (int i = 0; i < m; i++) {
      int u, v;
      cin >> u >> v;
      u--;
      v--;
      graph[u].push_back(v);
      graph[v].push_back(u);
      edges[i] = {u, v};
    }
    bcc bc(n);
    vector<int> comp(n);
    int nn = bc.find_edge_bcc(graph, comp);
    if (nn == 1) {
      cout << "0\n";
      continue;
    }
    vector<vector<int>> tree(nn);
    for (int i = 0; i < m; i++) {
      int u = edges[i].first, v = edges[i].second;
      if (comp[u] == comp[v]) continue;
      tree[comp[u]].push_back(comp[v]);
      tree[comp[v]].push_back(comp[u]);
    }
    vector<int> sz(nn);
    for (int i = 0; i < n; i++) {
      sz[comp[i]]++;
    }
    vector<int> cuts;
    bc.find_cutvertex(graph, cuts);
    if (find(cuts.begin(), cuts.end(), a) == cuts.end() ||
        find(cuts.begin(), cuts.end(), b) == cuts.end()) {
      cout << "0\n";
      continue;
    }
    vector<int> dp(nn), depth(nn);
    function<void(int, int, int)> dfs = [&](int u, int p, int d) {
      dp[u] = sz[u];
      depth[u] = d;
      for (int v : tree[u]) {
        if (v == p) continue;
        dfs(v, u, d + sz[u]);
        dp[u] += dp[v];
      }
    };
    dfs(0, -1, 0);
    lca lc(tree);
    if (comp[a] == comp[b]) {
      cout << "0\n";
      continue;
    }
    int c = lc.get(comp[a], comp[b]);
    int x = dp[comp[a]], y = dp[comp[b]];
    int d = abs(depth[comp[a]] - depth[comp[b]]);
    long long ans = 0;
    if (c != a && c != b) {
      ans = (long long)(x - 1) * (y - 1);
    } else if (c == a) {
      ans = (long long)(n - y - d + sz[comp[a]] - 1) * (y - 1);
    } else if (c == b) {
      ans = (long long)(n - x - d + sz[comp[b]] - 1) * (x - 1);
    }
    cout << max(0ll, ans) << '\n';
  }
  return 0;
}
