#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
inline void chmin(A &a, B b) {
  if (a > b) a = b;
}
template <typename A, typename B>
inline void chmax(A &a, B b) {
  if (a < b) a = b;
}
struct edge {
  long long to, cap, rev, id;
  edge(long long to, long long cap, long long rev, long long id)
      : to(to), cap(cap), rev(rev), id(id) {}
};
const long long INF = 1001001001;
vector<edge> G[222];
void add_edge(long long from, long long to, long long cap, long long id) {
  G[from].push_back(edge(to, cap, G[to].size(), id));
  G[to].push_back(edge(from, 0, G[from].size() - 1, -1));
}
bool used[222];
long long dfs(long long v, long long t, long long f) {
  if (v == t) return f;
  used[v] = true;
  for (auto &e : G[v]) {
    if (used[e.to] || e.cap == 0) continue;
    long long ff = dfs(e.to, t, min(f, e.cap));
    if (ff == 0) continue;
    e.cap -= ff;
    G[e.to][e.rev].cap += ff;
    return ff;
  }
  return 0;
}
long long max_flow(long long s, long long t) {
  long long f = 0;
  while (true) {
    memset(used, 0, sizeof(used));
    long long ff = dfs(s, t, INF);
    if (ff == 0) return f;
    f += ff;
  }
}
long long N, M, S, T;
long long A[1111], B[1111], C[1111];
bool ei[1111];
long long cap[1111];
vector<pair<long long, long long> > G2[1111];
bool dfs2(long long v, long long t) {
  used[v] = true;
  for (auto &e : G2[v]) {
    if (used[e.first]) continue;
    if (!dfs2(e.first, t)) continue;
    cap[e.second]++;
    return true;
  }
  return false;
}
signed main() {
  scanf("%lld%lld%lld%lld", &N, &M, &S, &T);
  S--;
  T--;
  for (long long i = 0; i < (M); i++) {
    scanf("%lld%lld%lld", &A[i], &B[i], &C[i]);
    A[i]--;
    B[i]--;
    if (C[i] == 0) {
      add_edge(A[i], B[i], INF, -1);
    } else {
      add_edge(B[i], A[i], INF, -1);
      add_edge(A[i], B[i], 1, i);
    }
  }
  printf("%lld\n", max_flow(S, T));
  memset(used, 0, sizeof(used));
  queue<long long> que;
  que.push(S);
  used[S] = true;
  while (que.size()) {
    long long v = que.front();
    que.pop();
    for (auto &e : G[v]) {
      if (e.cap == 0 || used[e.to]) continue;
      used[e.to] = true;
      que.push(e.to);
    }
  }
  for (long long i = 0; i < (222); i++) {
    for (auto &e : G[i]) {
      if (e.id == -1) continue;
      if (used[i] && !used[e.to]) ei[e.id] = true;
    }
  }
  for (long long i = 0; i < (M); i++) {
    if (C[i] == 0) continue;
    G2[A[i]].push_back({B[i], i});
  }
  for (long long i = 0; i < (M); i++) {
    if (C[i] == 0) {
      cap[i] = 1;
      continue;
    }
    memset(used, 0, sizeof(used));
    dfs2(S, A[i]);
    dfs2(B[i], T);
    cap[i]++;
  }
  for (long long i = 0; i < (M); i++) {
    long long f = cap[i];
    if (C[i] == 0)
      f = 0;
    else if (C[i] == 1 && !ei[i])
      cap[i]++;
    printf("%lld %lld\n", f, cap[i]);
  }
  return 0;
}
