#include <bits/stdc++.h>
using namespace std;
void debug() { cout << endl; }
template <class FIRST, class... REST>
void debug(FIRST arg, REST... rest) {
  cout << arg << " ";
  debug(rest...);
}
template <class T>
void showary(T begin, T end) {
  while (begin != end) {
    cout << *begin << " ";
    begin++;
  }
  cout << endl;
}
struct edge {
  int to, cost;
};
int N, M, P, Q;
vector<edge> G[100010];
bool used[100010];
long long loop(int at) {
  used[at] = true;
  long long res = 0;
  for (int i = 0; i < G[at].size(); i++) {
    edge e = G[at][i];
    res += e.cost;
    if (!used[e.to]) res += loop(e.to);
  }
  return res;
}
int main() {
  scanf("%d%d%d%d", &N, &M, &P, &Q);
  pair<int, int> rest(-1, -1);
  for (int i = 0; i < M; i++) {
    int t, f, c;
    scanf("%d%d%d", &t, &f, &c);
    t--;
    f--;
    G[t].push_back(edge{f, c});
    G[f].push_back(edge{t, c});
    if (rest.first == -1) rest = pair<int, int>(t, f);
  }
  priority_queue<pair<long long, int>, vector<pair<long long, int> >,
                 greater<pair<long long, int> > >
      que;
  for (int i = 0; i < N; i++) {
    if (used[i]) continue;
    que.push(pair<long long, int>(loop(i) / 2, i));
  }
  long long res = 0;
  vector<pair<int, int> > ans;
  for (int i = 0; i < P; i++) {
    if (que.size() > Q) {
      pair<long long, int> v1 = que.top();
      que.pop();
      pair<long long, int> v2 = que.top();
      que.pop();
      res += v1.first + v2.first + 1;
      que.push(pair<long long, int>(2 * (v1.first + v2.first) + 1, v1.second));
      ans.push_back(pair<int, int>(v1.second, v2.second));
      if (rest.first == -1) rest = pair<int, int>(v1.second, v2.second);
    } else {
      res += 1e9;
      if (rest.first != -1)
        ans.push_back(rest);
      else {
        cout << "NO" << endl;
        return 0;
      }
    }
  }
  if (que.size() != Q) {
    cout << "NO" << endl;
    return 0;
  } else {
    cout << "YES" << endl;
    for (int i = 0; i < P; i++) {
      printf("%d %d\n", ans[i].first + 1, ans[i].second + 1);
    }
  }
}
