#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}); }
                }
            }
        }
        vector<bool> U(N, false), V(N, false);
        queue<int> q1;
        q1.push(S - 1), U[S - 1] = true;
        while (not q1.empty()) {
            const int p = q1.front();
            q1.pop();
            for (const int to : g.edge[p]) {
                if (U[to]) { continue; }
                U[to] = true, q1.push(to);
            }
        }
        queue<int> q2;
        q2.push(T - 1), V[T - 1] = true;
        while (not q2.empty()) {
            const int p = q2.front();
            q2.pop();
            for (const int to : g.rev_edge[p]) {
                if (V[to]) { continue; }
                V[to] = true, q2.push(to);
            }
        }

        int ans = 0;
        for (const auto& e : E) {
            if (U[e.second] and V[e.first]) { ans++; }
        }
        cout << (F + (ans > 0 ? 1 : 0)) << " " << ans << endl;
    }
    return 0;
}



Measured memory_bytes: 3928