#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << (x) << endl
using namespace std;
constexpr int INF = 1 << 30;
template <typename Functor>
struct fix_type
{
    Functor functor;
    template <typename... Args>
    decltype(auto) operator()(Args&&... args) const& { return functor(functor, std::forward<Args>(args)...); }
};
template <typename Functor>
fix_type<typename std::decay<Functor>::type> fix(Functor&& functor) { return {std::forward<Functor>(functor)}; }
class Flow
{
public:
    struct Edge
    {
        int from, to, reverse, capacity, flow;
        const bool is_reverse;
    };
    Flow(const int v) : V{v}, edge(v) {}
    void addEdge(const int from, const int to, const int capacity)
    {
        edge[from].push_back(Edge{from, to, (int)edge[to].size(), capacity, 0, false});
        edge[to].push_back(Edge{to, from, (int)edge[from].size() - 1, capacity, capacity, true});
    }
    int FordFulkerson(const int s, const int t)
    {
        vector<bool> checked(V);
        auto dfs = fix([&](auto&& self, const int pos, const int flow) -> int {
            if (pos == t) { return flow; }
            checked[pos] = true;
            for (auto& e : edge[pos]) {
                if (not checked[e.to]) {
                    const int res = e.capacity - e.flow;
                    if (res > 0) {
                        const int d = self(self, e.to, min(flow, res));
                        if (d > 0) {
                            e.flow += min(d, res);
                            edge[e.to][e.reverse].flow -= min(d, res);
                            return d;
                        }
                    }
                }
            }
            return 0;
        });
        int flow = 0;
        while (true) {
            for (int i = 0; i < V; i++) { checked[i] = false; }
            const int f = dfs(s, INF);
            if (f == 0) { break; }
            flow += f;
        }
        return flow;
    }
    const int V;
    vector<vector<Edge>> edge;
};
struct Graph
{
    Graph(const int v) : V{v}, edge(v), rev_edge(v) {}
    void addEdge(const int from, const int to)
    {
        edge[from].push_back(to);
        rev_edge[to].push_back(from);
    }
    const int V;
    vector<vector<int>> edge;
    vector<vector<int>> rev_edge;
};

int main()
{
    while (true) {
        int N, M, S, T;
        cin >> N >> M >> S >> T;
        if (N == 0 and M == 0 and S == 0 and T == 0) { break; }
        Flow f(N);
        using P = pair<int, int>;
        for (int i = 0; i < M; i++) {
            int a, b;
            cin >> a >> b;
            f.addEdge(a - 1, b - 1, 1);
        }
        const int F = f.FordFulkerson(S - 1, T - 1);
        Graph g(N);
        vector<P> E;
        for (int i = 0; i < N; i++) {
            for (const auto& e : f.edge[i]) {
                if (not e.is_reverse) {
                    e.flow == 0 ? g.addEdge(e.from, e.to) : g.addEdge(e.to, e.from);
                    if (e.flow == 0) { E.push_back({e.from, e.to}); }
                }
            }
        }
        auto dijk = [&](const int s, const bool rev) -> vector<int> {
            vector<int> ans(N, INF);
            priority_queue<P, vector<P>, greater<P>> q;
            ans[s] = 0;
            q.push(make_pair(0, s));
            while (not q.empty()) {
                const P& p = q.top();
                const int cost = p.first;
                const int v = p.second;
                q.pop();
                if (ans[v] < cost) { continue; }
                for (const int to : (rev ? g.rev_edge[v] : g.edge[v])) {
                    if (ans[to] > ans[v] + 1) {
                        ans[to] = ans[v] + 1;
                        q.push(make_pair(ans[to], to));
                    }
                }
            }
            return ans;
        };
        const auto d = dijk(S - 1, false);
        const auto revd = dijk(T - 1, true);
        int ans = 0;
        for (const auto& e : E) {
            if (d[e.second] != INF and revd[e.first] != INF) { ans++; }
        }
        cout << (F + (ans > 0 ? 1 : 0)) << " " << ans << endl;
    }
    return 0;
}



Measured memory_bytes: 4064