#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

#include <complex>

#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#define debug(x) cerr << #x << " = " << (x) << endl;


#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 10010

struct Dinic{
  
  struct edge {
    int to, cap, rev;
    edge(int a, int b, int c):to(a),cap(b),rev(c){}
  };
  
  vector<vector<edge> > G;
  vector<int> level, iter;
  int MAX_V;
  
  Dinic(int max_v):G(max_v,vector<edge>()),MAX_V(max_v){}
  
  int add_edge(int from,int to,int cap){
    int id = G[from].size();
    
    G[from].push_back(edge(to,cap,G[to].size()));
    G[to].push_back(edge(from,0,G[from].size() - 1));
    
    return id;
  }
  
  void bfs(int s){
    level.assign(MAX_V,-1);
    queue<int> q;
    level[s] = 0;
    q.push(s);
    while(q.size()){
      int v = q.front(); q.pop();
      for(int i=0;i<G[v].size();i++){
        edge &e = G[v][i];
        if(e.cap > 0 && level[e.to] < 0){
          level[e.to] = level[v] + 1;
          q.push(e.to);
        }
      }
    }
  }
  
  int dfs(int v, int t, int f){
    if(v == t) return f;
    for(int &i = iter[v];i < G[v].size(); i++){
      edge &e = G[v][i];
      if(e.cap > 0 && level[v] < level[e.to]){
        int d = dfs(e.to, t, min(f,e.cap));
        if(d > 0){
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  
  int solve(int s, int t){
    int flow = 0;
    while(1){
      bfs(s);
      if(level[t] < 0) return flow;
      iter.assign(MAX_V,0);
      int f;
      while((f = dfs(s, t, INF)) > 0) flow += f;
    }
  }
  
};

void BFS(vector<int> *G, int s, bool *visited){
  queue<int> q;
  q.push(s);

  while(q.size()){
    int p = q.front();
    q.pop();

    if(visited[p]) continue;
    visited[p] = true;

    for(int i=0;i<G[p].size();i++)
      q.push(G[p][i]);
  }
}

void solve(int n, int m, int s, int t){
  int a[SIZE], b[SIZE];
  int id[SIZE];
  s--; t--;

  vector<int> G[SIZE];
  vector<int> rev[SIZE];
  
  Dinic dinic(n);

  for(int i=0;i<m;i++){
    scanf("%d%d",a+i, b+i);
    a[i]--; b[i]--;
    id[i] = dinic.add_edge(a[i], b[i], 1);
  }

  int value = dinic.solve(s, t);

  for(int i=0;i<m;i++){
    if(dinic.G[a[i]][id[i]].cap){
      G[a[i]].push_back(b[i]);
      rev[b[i]].push_back(a[i]);
    }else{
      rev[a[i]].push_back(b[i]);
      G[b[i]].push_back(a[i]);
    }
  }

  bool visited1[SIZE] = {};
  bool visited2[SIZE] = {};
  int counter = 0;
  
  BFS(G, s, visited1);
  BFS(rev, t, visited2);

  for(int i=0;i<m;i++){
    if(dinic.G[a[i]][id[i]].cap){
      if(visited1[b[i]] && visited2[a[i]]){
        counter++;
      }
    }
  }

  if(counter)
    printf("%d %d\n",value+1, counter);
  else
    printf("%d %d\n",value, 0);
  
  return;
}

int main(){
  int n,m,s,t;

  while(1){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    if(n == 0) break;
    solve(n,m,s,t);
  }
  
  return 0;
}

Measured memory_bytes: 4220