#include <bits/stdc++.h>
using namespace std;
vector<int> Z;
vector<long long> wart;
struct kraw {
  int a, b;
};
void Stworz(int n) {
  for (int i = 0; i < n; ++i) {
    Z.push_back(i);
    wart.push_back(0);
  }
}
int Find(int a) {
  if (Z[a] == a) return a;
  int fa = Find(Z[a]);
  Z[a] = fa;
  return fa;
}
void Union(int a, int b) {
  int fa = Find(a);
  int fb = Find(b);
  Z[fb] = fa;
}
int IlSpo() {
  set<int> S;
  for (int i = 0; i < Z.size(); ++i) S.insert(Find(i));
  return S.size();
}
int main() {
  ios_base::sync_with_stdio(0);
  int n, m, p, q;
  cin >> n >> m >> p >> q;
  Stworz(n);
  for (int i = 0; i < m; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    if (Find(a) == Find(b))
      wart[Find(a)] += c;
    else {
      wart[Find(a)] += wart[Find(b)];
      wart[Find(a)] += c;
      Union(a, b);
    }
  }
  int spo = IlSpo();
  if (q > spo || p < spo - q) {
    cout << "NO";
    return 0;
  }
  int x = spo - q;
  int y = p - x;
  set<pair<long long, int> > S;
  for (int i = 0; i < n; ++i) S.insert(make_pair(wart[Find(i)], Find(i)));
  vector<kraw> odp;
  for (int i = 0; i < x; ++i) {
    pair<long long, int> a = *S.begin();
    S.erase(S.begin());
    pair<long long, int> b = *S.begin();
    S.erase(S.begin());
    odp.push_back({a.second, b.second});
    long long c = min((long long)1000000000, a.first + b.first + 1);
    Union(a.second, b.second);
    S.insert(make_pair(a.first + b.first + c, a.second));
  }
  if (IlSpo() == n && y != 0) {
    cout << "NO";
    return 0;
  }
  cout << "YES" << endl;
  for (int i = 0; i < x; ++i)
    cout << odp[i].a + 1 << " " << odp[i].b + 1 << endl;
  vector<vector<int> > spoj(n);
  for (int i = 0; i < n; ++i) spoj[Find(i)].push_back(i);
  int nr;
  for (int i = 0; i < n; ++i)
    if (spoj[i].size() >= 2) nr = i;
  for (int i = 0; i < y; ++i)
    cout << spoj[nr][0] + 1 << " " << spoj[nr][1] + 1 << endl;
  return 0;
}
