Ikta has an extraordinary feeling for undirected graphs. Ikta likes the undirected graph G and its two-point s, t pair (G, s, t) that has the greatest "beauty". The "beauty" of a pair (G, s, t) is the edge e = \\ {u, v \\} (u and v are two different points of G), and the shortest path from s to t in G. Is the number of things whose length is greater than the length of the shortest path from s to t in the undirected graph with g plus e.

Your job is to write a program that seeks its "beauty" given a pair (G, s, t).



Input

The input is given in the following format.

> N M s t
> x1 y1
> ...
> xi yi
> ...
> xM yM
>

First, the number of vertices, the number of edges, and the integers N, M, s, t representing the two vertices of the undirected graph are input. From the 2nd line to the M + 1th line, two vertices connected by edges are input. (However, let the set of G vertices be \\ {1, ..., N \\}.)

Constraints

Each variable being input satisfies the following constraints.

* 2 ≤ N ≤ 100,000
* 1 ≤ M ≤ 300,000
* 1 ≤ s, t, xi, yi ≤ N
* Different from s and t
* Guaranteed to reach t from s

Output

When the given graph is G, output the "beauty" of the set (G, s, t) in one line.

Examples

Input

3 2 1 3
1 2
2 3


Output

1


Input

9 8 7 8
2 6
4 9
8 6
9 2
3 8
1 8
8 5
7 9


Output

7


Input

4 3 1 4
1 2
3 4
4 1


Output

0


Input

9 7 8 9
9 6
6 5
3 6
3 7
2 5
8 5
1 4


Output

2
/* monkukui 競技プログラミング用のテンプレート  (ここから) */
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <functional>
#include <bitset>

using namespace std;
using lint = long long int;
using ll = long long int;
using lnt = long long int;
using Graph = vector<vector<int>>;
using Wgraph = vector<vector<pair<int, long long int>>>;
constexpr long long int INF = 1001001001001001LL;
constexpr long long int MOD = 1000000007LL;
constexpr double PI = 3.1415926535897932;
constexpr long long int di[] = {-1, 0, 1, 0, -1, 1, 1, -1};
constexpr long long int dj[] = {0, 1, 0, -1, 1, 1, -1, -1};

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
inline void yes(){ cout << "yes" << endl; }
inline void Yes(){ cout << "Yes" << endl; }
inline void YES(){ cout << "YES" << endl; }
inline void no(){ cout << "no" << endl; }
inline void No(){ cout << "No" << endl; }
inline void NO(){ cout << "NO" << endl; }
inline void possible(){ cout << "possible" << endl; }
inline void Possible(){ cout << "Possible" << endl; }
inline void POSSIBLE(){ cout << "POSSIBLE" << endl; }
inline void impossible(){ cout << "impossible" << endl; }
inline void Impossible(){ cout << "Impossible" << endl; }
inline void IMPOSSIBLE(){ cout << "IMPOSSIBLE" << endl; }

#define REP(i,n) for(int i = 0; i < (n); i++)
#define RREP(i,n) for(int i = 1; i <= (n); i++)
#define DREP(i,n) for(int i = (n)-1; i >= 0; i--)
#define SREP(i,s,t) for(int i = s; i < t; i++)
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define PB push_back

/* monkukui 競技プログラミング用のテンプレート (ここまで)*/

// verified : http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A
// 負辺があると動作しない?
// O(E log V)
template<typename T>
vector<T> dijkstra(vector<vector<pair<int, T>>> &g, int s){
     
    int n = g.size();
    // numeric_limits がうまく使えない場合は自分で INF を定義する.
    const auto inf = numeric_limits<T>::max();
    vector<T> dist(n, inf);
 
    using P = pair<T, int>;
    // 小さい順に取り出せる
    priority_queue<P, vector<P>, greater<P>> que;
    dist[s] = 0;
    que.emplace(dist[s], s);
    while(!que.empty()){
        T cost;
        int node;
        tie(cost, node) = que.top();
        que.pop();
        if(dist[node] < cost) continue;
        for(auto &e : g[node]){
            auto next_cost = cost + e.second;
            int next_node = e.first;
            if(dist[next_node] <= next_cost) continue;
            dist[next_node] = next_cost;
            que.emplace(next_cost, next_node);
        }
    }
 
    return dist;
}

int main(){
  
  lnt n, m, s, t; cin >> n >> m >> s >> t;
  s--;
  t--;
  vector<vector<pair<int, lnt>>> g(n);
  for(int i = 0; i < m; i++) {
    lnt x, y; cin >> x >> y;
    x--;
    y--;
    g[x].push_back({y, 1});
    g[y].push_back({x, 1});
  }

  auto distFromS = dijkstra(g, s);
  auto distFromT = dijkstra(g, t);
  map<lnt, lnt> mpFromS;
  map<lnt, lnt> mpFromT;
  for(int i = 0; i < n; i++) mpFromS[distFromS[i]]++;
  for(int i = 0; i < n; i++) mpFromT[distFromT[i]]++;
  
  lnt ans = 0;
  lnt dist = distFromS[t];
  for(lnt x = 0; x < dist - 1; x++) {
    lnt y = dist - x - 2;
    ans += mpFromS[x] * mpFromT[y];
  }

  cout << ans << endl;

  return 0;
}

