#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;



#define _GLIBCXX_DEBUG

using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()


//const int INF = 2147483647;
//const long long int L_INF = 9223372036854775807;

typedef int Weight;

const Weight INF = INT_MAX;
const Weight ZERO = 0;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
	e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
#define RESIDUE(s,t) (capacity[s][t]-flow[s][t])

//??????0??????????????????????????¨??£???????±??????????????????§??¨???

int a = 0;
vector<vector<int>>froms(2);
Weight maximumFlow(const Graph &ag, int s, int t) {

	Graph g(ag);
	for (int i = 0; i < ag.size(); ++i) {
		for (int j = 0; j < ag[i].size(); ++j) {
			int d = ag[i][j].dst;
			int s = ag[i][j].src;

			bool ok = false;
			for (int k = 0; k < ag[d].size(); ++k) {
				if (ag[d][k].src == s) {
					ok = true;
					break;
				}
			}
			if (!ok) {
				g[d].push_back(Edge(d, s, ZERO));
			}
		}
	}
	int n = g.size();
	Matrix flow(n, Array(n,ZERO)), capacity(n, Array(n,ZERO));
	REP(u, n) FOR(e, g[u]) capacity[e->src][e->dst] =capacity[e->src][e->dst]+ e->weight;


	Weight total = ZERO;
	while (1) {
		queue<int> Q; Q.push(s);
		vector<int> prev(n, -1); prev[s] = s;
		while (!Q.empty() && prev[t] < 0) {
			int u = Q.front(); Q.pop();
			FOR(e, g[u]) if (prev[e->dst] < 0 && RESIDUE(u, e->dst) > ZERO) {
				prev[e->dst] = u;
				Q.push(e->dst);
			}
		}
		if (prev[t] < 0)break; // prev[x] == -1 <=> t-side
		Weight inc = INF;
		for (int j = t; prev[j] != j; j = prev[j]){
			auto v(RESIDUE(prev[j], j));
			if (inc > v) {
				inc = v;
			}
		}
		for (int j = t; prev[j] != j; j = prev[j])
			flow[prev[j]][j] =flow[prev[j]][j]+inc, flow[j][prev[j]] =flow[j][prev[j]]- inc;;
		total += inc;
	}
	
	{
		froms[a][s] = true;
		queue<int>que;
		que.push(s);
		while (!que.empty()) {
			int n = que.front();
			que.pop();
			for (auto e : g[n]) {
				if (RESIDUE(e.src, e.dst) > 0&&!froms[a][e.dst]) {
					froms[a][e.dst] = true;
					que.push(e.dst);
				}
			}
		}
	}

	a++;
	a %= 2;
	return total;
}

int main() {
	while (1) {
		int N, M, S, T; cin >> N >> M >> S >> T;
		if (!N)break;
		froms.clear();
		froms.resize(2);
		for (int i = 0; i < 2; ++i)froms[i].resize(N);
		S--; T--;
		for (int i = 0; i < N; ++i) {

		}
		Graph g(N);
		Graph revg(N);
		vector<vector<int>>anums(2,vector<int>(N));
		for (int i = 0; i < M; ++i) {
			int a, b; cin >> a >> b; a--; b--;
			anums[0][a]++;
			anums[1][b]++;
			auto it=find_if(g[a].begin(), g[a].end(), [=](const Edge&l) {
				return l.dst == b;
			});
			auto revit = find_if(revg[b].begin(), revg[b].end(), [=](const Edge&l) {
				return l.dst == a;
			});
			if(it==g[a].end()){


				g[a].push_back(Edge(a, b, 1));
				revg[b].push_back(Edge(b, a, 1));
			}
			else {
				it->weight++;
				revit->weight++;
			}
		}
		int nf = maximumFlow(g, S, T);
		maximumFlow(revg, T, S);
		int num=0;
		for (int i = 0; i < N; ++i) {
			for(auto e:revg[i]){

				if (froms[0][e.src] && froms[1][e.dst]) {
					num += e.weight;
				}
			}
		}
		if (num)nf++;
		cout << nf << " " << num << endl;
	}
	return 0;
}

Measured memory_bytes: 11436