#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
class edge {
 public:
  int e, nxt, cap;
  edge(int e1 = -1, int nxt1 = -1, int cap1 = 0) {
    e = e1, nxt = nxt1, cap = cap1;
  }
};
int S, T;
int dep[3010];
bool vis[3010];
class graph {
 public:
  edge g[3000000];
  int head[3010], tmpcnt;
  int cur[3010];
  void init() {
    memset(head, 255, sizeof(head));
    tmpcnt = 0;
  }
  void addedge(int s, int e, int cap) {
    if (cap == 0) return;
    g[tmpcnt] = edge(e, head[s], cap), head[s] = tmpcnt++;
    g[tmpcnt] = edge(s, head[e], 0), head[e] = tmpcnt++;
  }
  bool bfs() {
    memset(vis, 0, sizeof(vis));
    memset(dep, 0, sizeof(dep));
    queue<int> q;
    q.push(S);
    vis[S] = 1;
    while (!q.empty()) {
      int fr = q.front();
      q.pop();
      for (int i = head[fr]; i != -1; i = g[i].nxt) {
        if (g[i].cap > 0 && !vis[g[i].e]) {
          dep[g[i].e] = dep[fr] + 1;
          vis[g[i].e] = 1;
          q.push(g[i].e);
        }
      }
    }
    return vis[T];
  }
  int dfs(int np, int maxflow) {
    int f;
    int flow = 0;
    if (np == T || !maxflow) return maxflow;
    for (int i = cur[np]; i != -1; i = g[i].nxt) {
      cur[np] = i;
      if (g[i].cap > 0 && dep[g[i].e] == dep[np] + 1 &&
          (f = dfs(g[i].e, min(g[i].cap, maxflow))) > 0) {
        g[i].cap -= f;
        g[i ^ 1].cap += f;
        flow += f;
        maxflow -= f;
        if (!maxflow) break;
      }
    }
    return flow;
  }
  int dinic() {
    int out = 0;
    while (bfs()) memcpy(cur, head, sizeof(cur)), out += dfs(S, INF);
    return out;
  }
} G;
int n, p, s, t;
int st[1010], ed[1010], g[1010], f[1010], deg[1010];
int main() {
  G.init();
  scanf("%d%d%d%d", &n, &p, &s, &t);
  S = s, T = t;
  for (int i = 1; i <= p; i++) {
    scanf("%d%d%d", &st[i], &ed[i], &g[i]);
    if (g[i]) {
      G.addedge(ed[i], st[i], INF);
      G.addedge(st[i], ed[i], 1);
    } else {
      G.addedge(st[i], ed[i], INF);
    }
  }
  printf("%d\n", G.dinic());
  for (int i = 1; i <= p; i++)
    if (g[i] && vis[st[i]] && !vis[ed[i]]) f[i] = 1;
  G.init();
  S = n + 1, T = n + 2;
  for (int i = 1; i <= p; i++) {
    if (g[i]) {
      G.addedge(st[i], ed[i], INF);
      deg[st[i]]++;
      deg[ed[i]]--;
    }
  }
  G.addedge(t, s, INF);
  for (int i = 1; i <= n; i++) {
    if (deg[i] > 0)
      G.addedge(i, T, deg[i]);
    else
      G.addedge(S, i, -deg[i]);
  }
  G.dinic();
  int cnt = 0;
  for (int i = 1; i <= p; i++) {
    if (!g[i])
      puts("0 1");
    else {
      printf("%d %d\n", G.g[cnt << 1 | 1].cap + 1,
             G.g[cnt << 1 | 1].cap + (!f[i]) + 1);
      cnt++;
    }
  }
  return 0;
}
