#include <bits/stdc++.h>
using namespace std;
struct cell {
  long long root_vertix, com_len;
  cell() {}
  cell(long long x, long long y) {
    root_vertix = x;
    com_len = y;
  }
  bool operator<(const cell &x) const { return com_len < x.com_len; }
};
long long root[100002];
long long n, m, p, q;
long long find_root(long long x) {
  if (root[x] <= 0) return x;
  return root[x] = find_root(root[x]);
}
bool merge(long long x, long long y, long long len) {
  x = find_root(x);
  y = find_root(y);
  if (x == y) {
    root[x] -= len;
    return false;
  } else {
    root[x] = root[x] - len + root[y];
    root[y] = x;
    return 1;
  }
}
int main() {
  cin >> n >> m >> p >> q;
  long long components = n;
  fill(root, root + n + 1, 0);
  for (int i = 0; i < m; i++) {
    long long x, y, z;
    cin >> x >> y >> z;
    if (merge(x, y, z)) components--;
  }
  if (components < q || p < (components - q) ||
      (components == n && q == n && p > 0)) {
    cout << "NO" << endl;
    return 0;
  } else
    cout << "YES" << endl;
  priority_queue<cell> qq;
  for (int i = 1; i <= n; i++)
    if (root[i] <= 0) qq.push(cell(i, root[i]));
  long long diff = components - q;
  long long same = p - diff;
  while (diff--) {
    cell x, y;
    x = qq.top();
    qq.pop();
    y = qq.top();
    qq.pop();
    long long len = min((long long)1000000000, -x.com_len - y.com_len + 1);
    cout << x.root_vertix << " " << y.root_vertix << endl;
    merge(x.root_vertix, y.root_vertix, len);
    x.com_len = root[x.root_vertix];
    qq.push(x);
  }
  long long vertix;
  for (int i = 1; i <= n; i++)
    if (root[i] > 0) {
      vertix = i;
      break;
    }
  while (same--) cout << vertix << " " << root[vertix] << endl;
  return 0;
}
