#include <bits/stdc++.h>   #pragma GCC optimize( O3 )   using namespace std;   inline long long getint() {     long long _x = 0, _tmp = 1;     char _tc = getchar();     while ((_tc <  0  || _tc >  9 ) && _tc !=  - ) _tc = getchar();     if (_tc ==  - ) _tc = getchar(), _tmp = -1;     while (_tc >=  0  && _tc <=  9 ) _x *= 10, _x += (_tc -  0 ), _tc = getchar();     return _x * _tmp;   }   inline long long add(long long _x, long long _y,                        long long _mod = 1000000007LL) {     _x += _y;     return _x >= _mod ? _x - _mod : _x;   }   inline long long sub(long long _x, long long _y,                        long long _mod = 1000000007LL) {     _x -= _y;     return _x < 0 ? _x + _mod : _x;   }   inline long long mul(long long _x, long long _y,                        long long _mod = 1000000007LL) {     _x *= _y;     return _x >= _mod ? _x % _mod : _x;   }   long long mypow(long long _a, long long _x, long long _mod) {     if (_x == 0) return 1LL;     long long _ret = mypow(mul(_a, _a, _mod), _x >> 1, _mod);     if (_x & 1) _ret = mul(_ret, _a, _mod);     return _ret;   }   long long mymul(long long _a, long long _x, long long _mod) {     if (_x == 0) return 0LL;     long long _ret = mymul(add(_a, _a, _mod), _x >> 1, _mod);     if (_x & 1) _ret = add(_ret, _a, _mod);     return _ret;   }   inline bool equal(double _x, double _y) {     return _x > _y - 1e-9 && _x < _y + 1e-9;   }   int __ = 1, _cs;   struct Maxflow {     static const int MAXV = 20010;     struct Edge {       int v, c, r;       Edge(int _v, int _c, int _r) : v(_v), c(_c), r(_r) {}     };     int s, t;     vector<Edge> G[MAXV * 2];     int iter[MAXV * 2], d[MAXV * 2], gap[MAXV * 2], tot;     void init(int x) {       tot = x + 2;       s = x + 1, t = x + 2;       for (int i = 0; i <= tot; i++) {         G[i].clear();         iter[i] = d[i] = gap[i] = 0;       }     }     void addEdge(int u, int v, int c) {       G[u].push_back(Edge(v, c, (int)(G[v]).size()));       G[v].push_back(Edge(u, 0, (int)(G[u]).size() - 1));     }     int dfs(int p, int flow) {       if (p == t) return flow;       for (int &i = iter[p]; i < (int)(G[p]).size(); i++) {         Edge &e = G[p][i];         if (e.c > 0 && d[p] == d[e.v] + 1) {           int f = dfs(e.v, min(flow, e.c));           if (f) {             e.c -= f;             G[e.v][e.r].c += f;             return f;           }         }       }       if ((--gap[d[p]]) == 0)         d[s] = tot;       else {         d[p]++;         iter[p] = 0;         ++gap[d[p]];       }       return 0;     }     int solve() {       int res = 0;       gap[0] = tot;       for (res = 0; d[s] < tot; res += dfs(s, 1000000LL))         ;       return res;     }   } flow;   void build() {}   int n, m, s, t;   int ui[10210], vi[10210], gi[10210];   vector<int> g[10210], rg[10210];   void init() {     n = getint();     m = getint();     s = getint();     t = getint();     flow.init(n);     for (int i = 0; i < m; i++) {       ui[i] = getint();       vi[i] = getint();       gi[i] = getint();       g[ui[i]].push_back(i);       rg[vi[i]].push_back(i);       if (gi[i]) {         flow.addEdge(ui[i], vi[i], 1);         flow.addEdge(vi[i], ui[i], 1000000LL);       } else         flow.addEdge(ui[i], vi[i], 1000000LL);     }     flow.addEdge(flow.s, s, 1000000LL);     flow.addEdge(t, flow.t, 1000000LL);   }   set<int> reachable;   bool tg[10210], sat[10210];   int f[10210], c[10210];   int sbk[10210], sbke[10210];   int tbk[10210], tbke[10210];   bool vst[10210], vst2[10210];   int fucktag[10210], fuck;   bool go_to_s(int cur) {     assert(vst[cur]);     ++fuck;     int st = cur;     while (cur != s) {       if (fucktag[sbke[cur]] == fuck) return false;       fucktag[sbke[cur]] = fuck;       f[sbke[cur]]++;       cur = sbk[cur];       if (cur == st) return false;     }     return true;   }   bool go_to_t(int cur) {     assert(vst2[cur]);     ++fuck;     int st = cur;     while (cur != t) {       if (fucktag[tbke[cur]] == fuck) return false;       fucktag[tbke[cur]] = fuck;       f[tbke[cur]]++;       cur = tbk[cur];       if (cur == st) return false;     }     return true;   }   int ss[10210], stmp;   int who[10210], ee[10210];   bool find_cycle(int now, int st, int dep = 0) {     ss[now] = stmp;     who[dep] = now;     for (auto eid : g[now]) {       if (gi[eid] == 0) continue;       int nxt = vi[eid];       if (nxt == st) {         sbke[st] = eid;         sbk[st] = now;         vst[st] = true;         for (int i = 1; i <= dep; i++) {           sbk[who[i]] = who[i - 1];           vst[who[i]] = true;           sbke[who[i]] = ee[i - 1];         }         return true;       }       if (ss[nxt] == stmp) continue;       ee[dep] = eid;       if (find_cycle(nxt, st, dep + 1)) return true;     }     return false;   }   bool find_cycle2(int now, int st, int dep = 0) {     ss[now] = stmp;     who[dep] = now;     for (auto eid : rg[now]) {       if (gi[eid] == 0) continue;       int nxt = ui[eid];       if (nxt == st) {         tbke[st] = eid;         tbk[st] = now;         vst2[st] = true;         for (int i = 1; i <= dep; i++) {           tbk[who[i]] = who[i - 1];           vst2[who[i]] = true;           tbke[who[i]] = ee[i - 1];         }         return true;       }       if (ss[nxt] == stmp) continue;       ee[dep] = eid;       if (find_cycle2(nxt, st, dep + 1)) return true;     }     return false;   }   void pre_build() {     {       vst[s] = true;       queue<int> Q;       Q.push(s);       while (Q.size()) {         int tn = Q.front();         Q.pop();         for (auto eid : g[tn]) {           if (gi[eid] == 0) continue;           if (vst[vi[eid]]) continue;           vst[vi[eid]] = true;           sbk[vi[eid]] = ui[eid];           sbke[vi[eid]] = eid;           Q.push(vi[eid]);         }       }       for (int i = 1; i <= n; i++) {         if (!vst[i]) {           ++stmp;           if (find_cycle(i, i)) vst[i] = true;         }       }     }     {       vst2[t] = true;       queue<int> Q;       Q.push(t);       while (Q.size()) {         int tn = Q.front();         Q.pop();         for (auto eid : rg[tn]) {           if (gi[eid] == 0) continue;           if (vst2[ui[eid]]) continue;           vst2[ui[eid]] = true;           tbk[ui[eid]] = vi[eid];           tbke[ui[eid]] = eid;           Q.push(ui[eid]);         }       }       for (int i = 1; i <= n; i++)         if (!vst2[i]) {           ++stmp;           if (find_cycle2(i, i)) vst2[i] = true;         }     }   }   int ff[10210];   void solve() {     int ans = flow.solve();     queue<int> Q;     reachable.insert(s);     tg[s] = true;     Q.push(s);     while (Q.size()) {       int tn = Q.front();       Q.pop();       for (auto e : flow.G[tn]) {         if (e.c == 0) continue;         if (1 <= e.v and e.v <= n and !tg[e.v]) {           tg[e.v] = true;           Q.push(e.v);           reachable.insert(e.v);         }       }     }     int cc = 0;     for (int i = 0; i < m; i++)       if (reachable.find(ui[i]) != reachable.end() and           reachable.find(vi[i]) == reachable.end()) {         sat[i] = true;         ++cc;       }     assert(cc == ans);     pre_build();     for (int i = 0; i < m; i++) {       if (f[i]) continue;       if (gi[i] == 0) continue;       bool x = go_to_s(ui[i]);       bool y = go_to_t(vi[i]);       if (x and y) f[i]++;       if (f[i] == 0) f[i] = 1;     }     for (int i = 0; i < m; i++) {       if (gi[i] == 0)         c[i] = 1000000LL;       else {         c[i] = f[i];         if (!sat[i]) c[i]++;       }     }     ans = 0;     for (int i = 0; i < m; i++)       if (f[i] == c[i]) ans++;     printf( %d n , ans);     for (int i = 0; i < m; i++) {       printf( %d %d n , f[i], c[i]);       ff[ui[i]] -= f[i];       ff[vi[i]] += f[i];     }   }   int main() {     build();     while (__--) {       init();       solve();     }   }