#include <bits/stdc++.h>
using namespace std;
int read() {
  int w = 0, flg = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') {
      flg = -1;
    }
    ch = getchar();
  }
  while (ch <= '9' && ch >= '0') {
    w = w * 10 + ch - '0', ch = getchar();
  }
  return w * flg;
}
int head[110], ednum = 1;
struct edge {
  int nxt, to, w;
} ed[1010 * 5];
void add_Edge(int u, int v, int w) {
  ednum++;
  ed[ednum].nxt = head[u], ed[ednum].to = v, ed[ednum].w = w;
  head[u] = ednum;
}
int n, m, s1, t1, s2, t2, x[1010], y[1010], g[1010], id[1010];
int lev[110], cur[110], in[110], out[110];
bool is[110];
bool bfs(int s, int t) {
  memset(lev, 0x3f, sizeof(lev));
  queue<int> que;
  que.push(s);
  lev[s] = 0;
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    cur[u] = head[u];
    for (int i = head[u]; i; i = ed[i].nxt) {
      if (!ed[i].w) continue;
      int v = ed[i].to;
      if (lev[v] > lev[u] + 1) {
        lev[v] = lev[u] + 1;
        que.push(v);
      }
    }
  }
  return lev[t] != 0x3f3f3f3f;
}
int dfs(int u, int fl, int t) {
  if (u == t) return fl;
  int ret = 0;
  for (int &i = cur[u]; i; i = ed[i].nxt) {
    int v = ed[i].to;
    if (!ed[i].w || lev[v] != lev[u] + 1) continue;
    int k = dfs(v, min(fl, ed[i].w), t);
    ed[i].w -= k, ed[i ^ 1].w += k;
    ret += k, fl -= k;
    if (!fl) break;
  }
  return ret;
}
int dinic(int s, int t) {
  int re = 0;
  while (bfs(s, t)) re += dfs(s, 0x3f3f3f3f, t);
  return re;
}
int main() {
  n = read(), m = read(), s1 = read(), t1 = read(), s2 = n + 1, t2 = s2 + 1;
  for (int i = (1); i <= (m); i++) {
    x[i] = read(), y[i] = read(), g[i] = read();
    if (!g[i])
      add_Edge(x[i], y[i], 0x3f3f3f3f), add_Edge(y[i], x[i], 0);
    else {
      add_Edge(x[i], y[i], 1), add_Edge(y[i], x[i], 0);
      add_Edge(y[i], x[i], 0x3f3f3f3f), add_Edge(x[i], y[i], 0);
    }
  }
  printf("%d\n", dinic(s1, t1));
  for (int i = (1); i <= (n); i++)
    if (lev[i] != 0x3f3f3f3f) is[i] = true;
  ednum = 1;
  memset(head, 0, sizeof(head));
  memset(ed, 0, sizeof(ed));
  for (int i = (1); i <= (m); i++) {
    in[y[i]]++, out[x[i]]++;
    id[i] = ednum + 1;
    add_Edge(x[i], y[i], 0x3f3f3f3f - 1), add_Edge(y[i], x[i], 0);
  }
  for (int i = (1); i <= (n); i++) {
    if (in[i] > out[i])
      add_Edge(s2, i, in[i] - out[i]), add_Edge(i, s2, 0);
    else
      add_Edge(i, t2, out[i] - in[i]), add_Edge(t2, i, 0);
  }
  add_Edge(t1, s1, 0x3f3f3f3f), add_Edge(s1, t1, 0);
  dinic(s2, t2);
  for (int i = (1); i <= (m); i++) {
    if (!g[i])
      puts("0 1");
    else {
      if (is[x[i]] && !is[y[i]])
        printf("%d %d\n", ed[id[i]].w + 1, ed[id[i]].w + 1);
      else
        printf("%d %d\n", ed[id[i]].w + 1, ed[id[i]].w + 2);
    }
  }
  return 0;
}
