#include <bits/stdc++.h>   #pragma comment(linker,  /STACK:200000000 )   using namespace std;   const long long oo = 1LL << 60;   const long long kNumMoves = 4;   const long long kMoves[kNumMoves][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};   int n, v, e;   vector<int> a, b;   vector<vector<int> > conn, edges;   vector<int> ansX, ansY, ansD;   vector<int> topSort;   vector<int> seen;   void DFS_Topological(int node) {     if (seen[node]) return;     seen[node] = 1;     for (int i = 0; i < int(n); ++i) {       if (edges[node][i] && !seen[i]) {         DFS_Topological(i);         conn[node].push_back(i);         conn[i].push_back(node);       }     }     topSort.push_back(node);   }   int AddTransfusionStep(int src, int dest, int delta) {     int mxMoveOut = min(a[src], delta);     int mxMoveIn = min(v - a[dest], mxMoveOut);     a[src] -= mxMoveIn;     a[dest] += mxMoveIn;     if (mxMoveIn)       ansX.push_back(src + 1), ansY.push_back(dest + 1), ansD.push_back(mxMoveIn);     return mxMoveIn;   }   int Transfuse_Out(int node, int dest, int delta) {     if (!delta || seen[node] || seen[dest]) return 0;     int step1 = AddTransfusionStep(node, dest, delta);     if (step1 == delta) return delta;     for (int i = 0; i < int(conn[dest].size()); ++i) {       int newDest = conn[dest][i];       if (newDest == node) continue;       if (seen[newDest]) continue;       Transfuse_Out(dest, newDest, v);     }     int step2 = AddTransfusionStep(node, dest, delta - step1);     return step1 + step2;   }   int Transfuse_In(int node, int dest, int delta) {     if (!delta || seen[node] || seen[dest]) return 0;     int step1 = AddTransfusionStep(dest, node, delta);     if (step1 == delta) return delta;     for (int i = 0; i < int(conn[dest].size()); ++i) {       int newDest = conn[dest][i];       if (newDest == node) continue;       if (seen[newDest]) continue;       Transfuse_In(dest, newDest, v);     }     int step2 = AddTransfusionStep(dest, node, delta - step1);     return step1 + step2;   }   bool Transfuse(int node) {     int delta = a[node] - b[node];     if (delta > 0) {       for (int i = 0; i < int(conn[node].size()); ++i) {         int dest = conn[node][i];         if (seen[dest]) continue;         delta -= Transfuse_Out(node, dest, delta);       }       return (delta == 0 && a[node] == b[node]);     } else if (delta < 0) {       delta = -delta;       for (int i = 0; i < int(conn[node].size()); ++i) {         int dest = conn[node][i];         if (seen[dest]) continue;         delta -= Transfuse_In(node, dest, delta);       }       return (delta == 0 && a[node] == b[node]);     }     return true;   }   bool FindTransfusions() {     seen.clear();     seen.resize(n, 0);     for (int i = 0; i < int(n); ++i) DFS_Topological(i);     seen.clear();     seen.resize(n, 0);     for (int i = 0; i < int(n); ++i) {       if (!Transfuse(topSort[i])) return false;       seen[topSort[i]] = 1;     }     return true;   }   int main() {     cin >> n >> v >> e;     a.resize(n), b.resize(n);     for (int i = 0; i < int(n); ++i) cin >> a[i];     for (int i = 0; i < int(n); ++i) cin >> b[i];     conn.resize(n);     edges.resize(n, vector<int>(n, 0));     for (int i = 0; i < int(e); ++i) {       int x, y;       cin >> x >> y;       --x, --y;       edges[x][y] = edges[y][x] = 1;     }     if (FindTransfusions()) {       cout << ansX.size() << endl;       for (int i = 0; i < int(ansX.size()); ++i)         cout << ansX[i] <<     << ansY[i] <<     << ansD[i] << endl;     } else {       cout <<  NO ;     }     int i;     cin >> i;     return 0;   }