#include <bits/stdc++.h>
using namespace std;
const int N = 1005, M = 10005;
using ll = long long;
const ll inf = LLONG_MAX >> 5;
struct FlowGraph {
  int head[N], v[M], nxt[M], ptr, t;
  ll w[M];
  inline void padd_edge(int uu, int vv, ll ww) {
    v[ptr] = vv;
    w[ptr] = ww;
    nxt[ptr] = head[uu];
    head[uu] = ptr++;
  }
  int dis[N], cur[N];
  bool vis[N];
  bool bfs(int s, int t) {
    memset(vis, 0, sizeof(vis));
    memset(dis, -1, sizeof(dis));
    queue<int> q;
    q.push(s);
    dis[s] = 1;
    while (!q.empty()) {
      int nd = q.front();
      q.pop();
      for (int i = head[nd]; i != -1; i = nxt[i])
        if (w[i] && dis[v[i]] == -1) {
          dis[v[i]] = dis[nd] + 1;
          q.push(v[i]);
        }
    }
    return dis[t] != -1;
  }
  ll dfs(int pos, ll flow) {
    if (pos == t) return flow;
    ll tmp = flow;
    for (int &i = cur[pos]; i != -1; i = nxt[i])
      if (w[i] && dis[v[i]] == dis[pos] + 1) {
        ll fl = dfs(v[i], min(flow, w[i]));
        w[i] -= fl;
        w[i ^ 1] += fl;
        flow -= fl;
        if (!flow) break;
      }
    if (flow) dis[pos] = -1;
    return tmp - flow;
  }
  FlowGraph() {
    memset(head, -1, sizeof(head));
    memset(nxt, -1, sizeof(nxt));
  }
  inline void add_edge(int uu, int vv, ll ww) {
    padd_edge(uu, vv, ww);
    padd_edge(vv, uu, 0);
  }
  ll dinic(int s, int t) {
    this->t = t;
    ll ret = 0;
    while (bfs(s, t)) memcpy(cur, head, sizeof(cur)), ret += dfs(s, inf);
    return ret;
  }
} g;
int ans, be[N], ans2[N], in[N], n, m, s, t;
struct Edge {
  int x, y, g;
} a[M];
int main() {
  ios::sync_with_stdio(false);
  cin >> n >> m >> s >> t;
  for (int i = 1; i <= m; i++) {
    cin >> a[i].x >> a[i].y >> a[i].g;
    if (a[i].x == s && a[i].y == t)
      ++ans;
    else if (!a[i].g)
      g.add_edge(a[i].x, a[i].y, inf);
    else
      g.add_edge(a[i].x, a[i].y, 1), g.add_edge(a[i].y, a[i].x, inf);
  }
  ans += g.dinic(s, t);
  cout << ans << endl;
  int ss = n + 1, tt = n + 2;
  for (int i = 1; i <= n; i++) be[i] = (g.dis[i] != -1);
  memset(g.head, -1, sizeof(g.head));
  g.ptr = 0;
  for (int i = 1; i <= m; i++)
    if (a[i].g) {
      ans2[i] = g.ptr;
      g.add_edge(a[i].x, a[i].y, 10000);
      ++in[a[i].y];
      --in[a[i].x];
    }
  for (int i = 1; i <= n; i++)
    if (in[i] > 0)
      g.add_edge(ss, i, in[i]);
    else
      g.add_edge(i, tt, -in[i]);
  g.add_edge(tt, ss, inf);
  g.dinic(ss, tt);
  for (int i = 1; i <= m; i++) {
    if (a[i].x == s && a[i].y == t)
      cout << "1 1\n";
    else if (!a[i].g)
      cout << "0 1\n";
    else {
      int ww = 10001 - g.w[ans2[i]];
      cout << ww << ' ' << (be[a[i].x] > be[a[i].y] ? ww : 100000) << endl;
    }
  }
  return 0;
}
