#include <bits/stdc++.h>   using namespace std;   template <typename T>   class flow_graph {    public:     static constexpr T eps = (T)1e-9;     struct edge {       int from;       int to;       T c;       T f;     };     vector<vector<int>> g;     vector<edge> edges;     int n;     int st;     int fin;     T flow;     flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) {       assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin);       g.resize(n);       flow = 0;     }     void clear_flow() {       for (const edge &e : edges) {         e.f = 0;       }       flow = 0;     }     int add(int from, int to, T forward_cap, T backward_cap) {       assert(0 <= from && from < n && 0 <= to && to < n);       int id = (int)edges.size();       g[from].push_back(id);       edges.push_back({from, to, forward_cap, 0});       g[to].push_back(id + 1);       edges.push_back({to, from, backward_cap, 0});       return id;     }   };   template <typename T>   class dinic {    public:     flow_graph<T> &g;     vector<int> ptr;     vector<int> d;     vector<int> q;     dinic(flow_graph<T> &_g) : g(_g) {       ptr.resize(g.n);       d.resize(g.n);       q.resize(g.n);     }     bool expath() {       fill(d.begin(), d.end(), -1);       q[0] = g.fin;       d[g.fin] = 0;       int beg = 0, end = 1;       while (beg < end) {         int i = q[beg++];         for (int id : g.g[i]) {           const auto &e = g.edges[id];           const auto &back = g.edges[id ^ 1];           if (back.c - back.f > g.eps && d[e.to] == -1) {             d[e.to] = d[i] + 1;             if (e.to == g.st) {               return true;             }             q[end++] = e.to;           }         }       }       return false;     }     T dfs(int v, T w) {       if (v == g.fin) {         return w;       }       int &j = ptr[v];       while (j >= 0) {         int id = g.g[v][j];         const auto &e = g.edges[id];         if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) {           T t = dfs(e.to, min(e.c - e.f, w));           if (t > g.eps) {             g.edges[id].f += t;             g.edges[id ^ 1].f -= t;             return t;           }         }         j--;       }       return 0;     }     T max_flow() {       while (expath()) {         for (int i = 0; i < g.n; i++) {           ptr[i] = (int)g.g[i].size() - 1;         }         T big_add = 0;         while (true) {           T add = dfs(g.st, numeric_limits<T>::max());           if (add <= g.eps) {             break;           }           big_add += add;         }         if (big_add <= g.eps) {           break;         }         g.flow += big_add;       }       return g.flow;     }     vector<bool> min_cut() {       max_flow();       vector<bool> ret(g.n);       for (int i = 0; i < g.n; i++) {         ret[i] = (d[i] != -1);       }       return ret;     }   };   template <typename T>   void debug_out(T t) {     cerr << t;   }   template <typename A, typename B>   void debug_out(pair<A, B> u) {     cerr <<  (  << u.first <<     << u.second <<  ) ;   }   template <typename T>   void debug_out(vector<T> t) {     int sz = t.size();     for (int i = 0; i < sz; i++) {       debug_out(t[i]);       if (i != sz - 1) cerr <<  ,  ;     }   }   template <typename T>   void debug_out(vector<vector<T>> t) {     int sz = t.size();     for (int i = 0; i < sz; i++) {       debug_out(t[i]);       if (i != sz - 1) cerr << endl;     }   }   int n, m, s, t;   struct edge {     int u, v, c, f;     int id;     edge(){};     edge(int _u, int _v, int _c, int _f, int _id)         : u(_u), v(_v), c(_c), f(_f), id(_id){};   };   int main() {     cin >> n >> m >> s >> t;     s--;     t--;     flow_graph<int> st(n, s, t);     vector<edge> res;     vector<vector<int>> edges(n);     vector<vector<int>> sp(n);     vector<int> rev(m);     const int inf = 1e9;     for (int i = 0; i < m; i++) {       int u, v, g;       cin >> u >> v >> g;       u--;       v--;       res.emplace_back(u, v, 0, 0, res.size());       if (g) {         edges[u].push_back(res.size() - 1);         sp[v].push_back(res.size() - 1);       }       rev[i] = g;       st.add(u, v, (g ? 1 : inf), (g ? inf : 0));     }     dinic<int> g(st);     vector<bool> ret = g.min_cut();     vector<int> sat(m);     int cnt = 0;     for (edge e : res) {       if (!ret[e.u] && ret[e.v]) {         sat[e.id] = 1;         cnt++;       }     }     cout << cnt << endl;     vector<vector<int>> stt(n), fin(n);     vector<int> cur;     vector<int> alive(n);     function<void(int)> dfs = [&](int v) {       alive[v] = 1;       stt[v] = cur;       for (auto i : edges[v]) {         int u = res[i].v;         if (alive[u]) continue;         cur.push_back(i);         dfs(u);         cur.pop_back();       }     };     for (int rot = 0; rot < 2; rot++) {       fill(alive.begin(), alive.end(), 0);       dfs(rot ? t : s);       swap(stt, fin);       for (auto &i : res) swap(i.u, i.v);       swap(edges, sp);     }     for (int i = 0; i < m; i++) {       int u = res[i].u, v = res[i].v;       if (!res[i].f && rev[res[i].id]) {         for (auto j : stt[u]) res[j].f++;         for (auto j : fin[v]) res[j].f++;         res[i].f++;       }     }     for (auto &i : res) {       if (sat[i.id]) {         i.c = i.f;       } else         i.c = inf;     }     for (auto i : res) {       cout << i.f <<     << i.c << endl;     }     return 0;   }