Little town Nsk consists of n junctions connected by m bidirectional roads. Each road connects two distinct junctions and no two roads connect the same pair of junctions. It is possible to get from any junction to any other junction by these roads. The distance between two junctions is equal to the minimum possible number of roads on a path between them.

In order to improve the transportation system, the city council asks mayor to build one new road. The problem is that the mayor has just bought a wonderful new car and he really enjoys a ride from his home, located near junction s to work located near junction t. Thus, he wants to build a new road in such a way that the distance between these two junctions won't decrease. 

You are assigned a task to compute the number of pairs of junctions that are not connected by the road, such that if the new road between these two junctions is built the distance between s and t won't decrease.

Input

The firt line of the input contains integers n, m, s and t (2 ≤ n ≤ 1000, 1 ≤ m ≤ 1000, 1 ≤ s, t ≤ n, s ≠ t) — the number of junctions and the number of roads in Nsk, as well as the indices of junctions where mayors home and work are located respectively. The i-th of the following m lines contains two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi), meaning that this road connects junctions ui and vi directly. It is guaranteed that there is a path between any two junctions and no two roads connect the same pair of junctions.

Output

Print one integer — the number of pairs of junctions not connected by a direct road, such that building a road between these two junctions won't decrease the distance between junctions s and t.

Examples

Input

5 4 1 5
1 2
2 3
3 4
4 5


Output

0


Input

5 4 3 5
1 2
2 3
3 4
4 5


Output

5


Input

5 6 1 5
1 2
1 3
1 4
4 5
3 5
2 5


Output

3
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.io.IOException;
import java.io.Writer;
import java.util.NoSuchElementException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author palayutm
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        ProblemDFightAgainstTraffic solver = new ProblemDFightAgainstTraffic();
        solver.solve(1, in, out);
        out.close();
    }

    static class ProblemDFightAgainstTraffic {
        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt(), m = in.nextInt(), S = in.nextInt(), T = in.nextInt();
            boolean[][] a = new boolean[n + 1][n + 1];
            int[] dis = new int[n + 1];
            Arrays.fill(dis, -1);
            dis[S] = 0;
            int[] pre = new int[n + 1];
            Graph g = new Graph(n + 1);
            for (int i = 0; i < m; i++) {
                int u = in.nextInt(), v = in.nextInt();
                g.addWeightedEdge(u, v, 1);
                g.addWeightedEdge(v, u, 1);
                a[u][v] = a[v][u] = true;
            }
            ShortestPath sp1 = new SPFA(g, S), sp2 = new SPFA(g, T);
            long d = sp1.getDistance(T);
            int cnt = 0;
            for (int i = 1; i <= n; i++) {
                for (int j = i + 1; j <= n; j++) {
                    if (!a[i][j]) {
                        if (sp1.getDistance(i) + sp2.getDistance(j) + 1 >= d &&
                                sp1.getDistance(j) + sp2.getDistance(i) + 1 >= d) {
                            cnt++;
                        }
                    }
                }
            }
            out.println(cnt);
        }

    }

    static class SPFA implements ShortestPath {
        long[] dis;

        public SPFA(Graph g, int from) {
            int n = g.getVertexNumber();
            dis = new long[n];
            ArrayUtil.fill(dis, Long.MAX_VALUE);
            boolean[] vis = new boolean[n];
            dis[from] = 0;
            vis[from] = true;
            IntDeque q = new IntDeque();
            q.addLast(from);
            while (!q.isEmpty()) {
                int u = q.removeFirst();
                vis[u] = false;
                for (Edge e : g.getEdges(u)) {
                    if (dis[u] + e.weight < dis[e.to]) {
                        dis[e.to] = dis[u] + e.weight;
                        if (!vis[e.to]) {
                            vis[e.to] = true;
                            q.addLast(e.to);
                        }
                    }
                }
            }
        }


        public long getDistance(int to) {
            return dis[to];
        }

    }

    static class IntDeque {
        private static final int DEFAULT_CAPACITY = 8;
        int[] deque;
        int size;
        int head;
        int tail;
        int mask;

        public IntDeque() {
            this(DEFAULT_CAPACITY);
        }

        public IntDeque(int capacity) {
            int L = 2;
            while (L < capacity) L <<= 1;
            deque = new int[L];
            size = head = tail = 0;
            mask = L - 1;
        }

        public boolean isEmpty() {
            return size == 0;
        }

        public void addLast(int value) {
            if (size == deque.length) {
                enLarge();
            }
            deque[tail] = value;
            tail = (tail + 1) & mask;
            size++;
        }

        public int removeFirst() {
            if (size == 0) {
                throw new NoSuchElementException();
            }
            final int removed = deque[head];
            head = (head + 1) & mask;
            size--;
            return removed;
        }

        private void enLarge() {
            int newSize = (size << 1);
            int[] newArray = new int[newSize];
            System.arraycopy(deque, head, newArray, 0, deque.length - head);
            System.arraycopy(deque, 0, newArray, deque.length - tail, tail);
            deque = newArray;
            head = 0;
            tail = size;
            mask = deque.length - 1;
        }

    }

    static class ArrayUtil {
        public static void fill(long[] a, long value) {
            Arrays.fill(a, value);
        }

    }

    static class Edge {
        public int to;
        public long weight;

        public Edge(int to) {
            this.to = to;
        }

        public Edge(int to, long weight) {
            this(to);
            this.weight = weight;
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0;
        private int ptrbuf = 0;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private int readByte() {
            if (lenbuf == -1) throw new UnknownError();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = stream.read(inbuf);
                } catch (IOException e) {
                    throw new UnknownError();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

    }

    static class MyArrayList<T> implements Iterable<T> {
        private static final int DEFAULT_CAPACITY = 10;
        private static final double ENLARGE_SCALE = 2.0;
        Object[] array;
        int size;

        public MyArrayList() {
            this(DEFAULT_CAPACITY);
        }

        public MyArrayList(int capacity) {
            array = new Object[capacity];
            size = 0;
        }

        public void add(T value) {
            if (size == array.length) {
                enLarge();
            }
            array[size++] = value;
        }

        private void enLarge() {
            Object[] newArray = new Object[(int) (array.length * ENLARGE_SCALE)];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }


        public Iterator<T> iterator() {
            return new Iterator<T>() {
                private int currentIndex = 0;


                public boolean hasNext() {
                    return currentIndex < size;
                }


                public T next() {
                    return (T) array[currentIndex++];
                }
            };
        }

    }

    static interface ShortestPath {
        public long getDistance(int to);

    }

    static class Graph {
        MyArrayList<Edge>[] g;

        public Graph(int n) {
            g = new MyArrayList[n];
            for (int i = 0; i < n; i++) {
                g[i] = new MyArrayList();
            }
        }

        public void addWeightedEdge(int from, int to, long weight) {
            g[from].add(new Edge(to, weight));
        }

        public MyArrayList<Edge> getEdges(int from) {
            return g[from];
        }

        public int getVertexNumber() {
            return g.length;
        }

    }

    static class OutputWriter extends PrintWriter {
        public OutputWriter(OutputStream out) {
            super(out);
        }

        public OutputWriter(Writer out) {
            super(out);
        }

        public void close() {
            super.close();
        }

    }
}

