#include <bits/stdc++.h>
using namespace std;
struct union_find {
  vector<int> p;
  union_find(int n) : p(n, -1) {}
  bool join(int u, int v) {
    if ((u = root(u)) == (v = root(v))) return false;
    if (p[u] > p[v]) swap(u, v);
    p[u] += p[v];
    p[v] = u;
    return true;
  }
  int root(int u) { return p[u] < 0 ? u : p[u] = root(p[u]); }
  int size(int u) { return -p[root(u)]; }
};
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  const long long inf = 1e9;
  int n, m, p, q;
  cin >> n >> m >> p >> q;
  set<pair<long long, int>> dp;
  vector<long long> mp(n);
  for (int i = 0; i < n; ++i) dp.insert({0LL, i});
  int su = -1, sv;
  union_find uf(n);
  vector<pair<int, int>> ans;
  auto merge = [&](int u, int v, long long add) {
    su = u, sv = v;
    if (add == -1) ans.push_back({u, v});
    int ru = uf.root(u);
    int rv = uf.root(v);
    if (ru != rv) {
      long long c = mp[ru] + mp[rv];
      if (add == -1) add = min(c + 1, inf);
      dp.erase({mp[ru], ru});
      dp.erase({mp[rv], rv});
      uf.join(ru, rv);
      ru = uf.root(ru);
      mp[ru] = c + add;
      dp.insert({c + add, ru});
    } else {
      if (add == -1) add = 1000;
      dp.erase({mp[ru], ru});
      mp[ru] += add;
      dp.insert({mp[ru], ru});
    }
  };
  for (int i = 0, u, v, w; i < m; ++i) {
    cin >> u >> v >> w;
    --u, --v;
    merge(u, v, w);
  }
  while (dp.size() > q && p > 0) {
    int u = dp.begin()->second;
    int v = next(dp.begin())->second;
    merge(u, v, -1);
    --p;
  }
  if (dp.size() != q || (p > 0 && su == -1)) {
    cout << "NO\n";
    return 0;
  }
  while (p > 0) ans.push_back({su, sv}), --p;
  cout << "YES\n";
  for (auto &i : ans) cout << i.first + 1 << " " << i.second + 1 << "\n";
  return 0;
}
