#include <bits/stdc++.h>
using namespace std;
inline long long Max(long long x, long long y) { return x > y ? x : y; }
inline long long Min(long long x, long long y) { return x < y ? x : y; }
inline void read(long long &x) {
  x = 0;
  long long f = 1;
  char s = getchar();
  while (s < '0' || s > '9') {
    if (s == '-') f = -1;
    s = getchar();
  }
  while (s >= '0' && s <= '9') {
    x = (x << 3) + (x << 1) + (s ^ 48);
    s = getchar();
  }
  x *= f;
}
long long Fa[100005], Val[100005];
struct node {
  long long v, w;
  node() {}
  node(long long V, long long W) {
    v = V;
    w = W;
  }
  friend bool operator<(node A, node B) { return A.w > B.w; }
};
vector<node> G[100005];
long long UU, VV, totB;
priority_queue<node> Q;
bool Vis[100005];
void Dfs(long long x, long long Pre, long long Zx) {
  Vis[x] = 1;
  int l = G[x].size();
  for (register int i = 0; i < l; ++i) {
    long long to = G[x][i].v;
    Val[Zx] += G[x][i].w;
    if (Vis[to]) continue;
    Dfs(to, x, Zx);
  }
}
long long Ltk, Xx[100005], Yy[100005], Way;
int main() {
  long long n, m, p, q;
  read(n);
  read(m);
  read(p);
  read(q);
  for (register int i = 1; i <= m; ++i) {
    long long u, v, w;
    read(u);
    read(v);
    read(w);
    G[u].push_back(node(v, w));
    G[v].push_back(node(u, w));
    UU = u, VV = v;
  }
  for (register int i = 1; i <= n; ++i)
    if (!Vis[i]) {
      Dfs(i, i, i);
      Q.push(node(i, Val[i] / 2));
      Ltk++;
    }
  long long Add = Ltk - q;
  if (p < Add || Add < 0) return !printf("NO");
  p -= Add;
  while (Add--) {
    node Q1 = Q.top();
    Q.pop();
    node Q2 = Q.top();
    Q.pop();
    UU = Xx[++Way] = Q1.v, VV = Yy[Way] = Q2.v;
    long long now = Min(Q1.w + Q2.w + 1, 1000000000);
    Q.push(node(Q1.v, Min(1000000000, Q1.w + Q2.w + now)));
  }
  while (p--) {
    if (!UU || !VV) return !printf("NO");
    Xx[++Way] = UU, Yy[Way] = VV;
  }
  printf("YES\n");
  for (register int i = 1; i <= Way; ++i) printf("%lld %lld\n", Xx[i], Yy[i]);
  return 0;
}
