#include <bits/stdc++.h>
using namespace std;
long long get() {
  long long x = 0;
  char s = getchar();
  while (s < '0' || s > '9') s = getchar();
  while (s >= '0' && s <= '9')
    x = (x << 3) + (x << 1) + (s ^ 48), s = getchar();
  return x;
}
long long Min(const long long x, const long long y) {
  if (x < y) return x;
  return y;
}
const long long M = 1e5 + 5;
long long n, m, p, q, tot, f[M], siz[M];
struct node {
  long long x, siz;
  node() {}
  node(const long long X, const long long S) { x = X, siz = S; }
  bool operator<(const node t) const { return siz > t.siz; }
} t1, t2;
priority_queue<node> Q;
long long Find(const long long x) {
  if (f[x] ^ x) f[x] = Find(f[x]);
  return f[x];
}
void unite(long long u, long long v, const long long l) {
  u = Find(u), v = Find(v);
  if (u == v)
    siz[u] += l;
  else {
    f[u] = v;
    siz[v] += siz[u] + l;
    --tot;
  }
}
signed main() {
  n = tot = get(), m = get(), p = get(), q = get();
  for (long long i = 1; i <= n; ++i) f[i] = i;
  for (long long u, v, l, i = 1; i <= m; ++i) {
    u = get(), v = get(), l = get();
    unite(u, v, l);
  }
  if (tot - p > q || tot < q || (!m && n == q && p)) return !printf("NO");
  printf("YES\n");
  for (long long i = 1; i <= n; ++i)
    if (Find(i) == i) Q.push(node(i, siz[i]));
  while (tot > q) {
    t1 = Q.top(), Q.pop();
    t2 = Q.top(), Q.pop();
    --p, --tot;
    printf("%lld %lld\n", t1.x, t2.x);
    f[t2.x] = t1.x;
    siz[t1.x] += Min((long long)1e9, t1.siz + t2.siz + 1) + t2.siz;
    Q.push(node(t1.x, siz[t1.x]));
  }
  for (tot = 1; tot <= n; ++tot)
    if (Find(tot) ^ tot) break;
  while (p--) printf("%lld %lld\n", tot, f[tot]);
  return 0;
}
