#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void Read(T &x) {
  int f = 1;
  char t = getchar();
  while (t < '0' || t > '9') {
    if (t == '-') f = -1;
    t = getchar();
  }
  x = 0;
  while (t >= '0' && t <= '9') {
    x = x * 10 + t - '0';
    t = getchar();
  }
  x *= f;
}
template <class T>
inline void chkmin(T &x, T y) {
  if (x > y) x = y;
}
template <class T>
inline void chkmax(T &x, T y) {
  if (x < y) x = y;
}
const double eps = 1e-10;
const int tl = 0.2 * CLOCKS_PER_SEC;
const int inf = 0x3f3f3f3f;
const int maxn = 100005;
const int maxk = 6;
struct point {
  double x, y;
  point() {}
  point(double x, double y) : x(x), y(y) {}
};
point operator+(point a, point b) { return point(a.x + b.x, a.y + b.y); }
point operator-(point a, point b) { return point(a.x - b.x, a.y - b.y); }
point operator/(point a, double v) { return point(a.x / v, a.y / v); }
point operator*(point a, double v) { return point(a.x * v, a.y * v); }
double operator^(point a, point b) { return a.x * b.y - a.y * b.x; }
struct line {
  point c, v;
  line() {}
  line(point a, point b) { c = a, v = b - a; }
};
struct equ {
  double A, B, C;
  void read() {
    scanf("%lf%lf%lf", &A, &B, &C);
    if (fabs(A) < eps) {
      C /= B;
      B = 1;
    } else {
      B /= A;
      C /= A;
      A = 1;
    }
  }
  line toline() {
    if (fabs(A) < eps)
      return line(point(0, -C), point(1, -C));
    else if (fabs(B) < eps)
      return line(point(-C, 0), point(-C, 1));
    else
      return line(point(0, -C / B), point(1, (-A - C) / B));
  }
  bool operator==(const equ &rhs) const {
    return fabs(A - rhs.A) < eps && fabs(B - rhs.B) < eps &&
           fabs(C - rhs.C) < eps;
  }
  bool parallel(const equ &rhs) {
    if ((fabs(A) < eps && fabs(rhs.B) < eps) ||
        (fabs(B) < eps && fabs(rhs.A) < eps))
      return false;
    else
      return fabs(A * rhs.B - B * rhs.A) < eps;
  }
  bool contain(const point &p) { return fabs(A * p.x + B * p.y + C) < eps; }
};
point intersection(line a, line b) {
  point u = b.c - a.c;
  double t = (u ^ a.v) / (a.v ^ b.v);
  return b.c + b.v * t;
}
int n;
int k;
equ fun[maxn];
line seg[maxn];
pair<int, int> ans[maxk];
void input() {
  Read(n);
  Read(k);
  for (int i = 1; i <= n; i++) {
    fun[i].read();
    seg[i] = fun[i].toline();
  }
}
bool dfs(const vector<int> &res, int dep) {
  if (res.size() == 0 || dep >= (int)res.size()) {
    if (dep >= (int)res.size()) {
      for (int i = 0; i < (int)res.size(); i++) {
        ans[dep] = make_pair(res[i], -1);
        dep--;
      }
    }
    printf("YES\n");
    printf("%d\n", k - dep);
    for (int i = k; i > dep; i--) {
      printf("%d %d\n", ans[i].first, ans[i].second);
    }
    return true;
  }
  if (dep == 0) return false;
  vector<int> nex;
  int trial = 100;
  int limit = (dep * dep < (int)res.size()) ? dep + 1 : 0;
  while (trial--) {
    while (clock() > tl) return false;
    int x = rand() % res.size();
    int y = rand() % res.size();
    nex.clear();
    if (x == y) {
      for (int i = 0; i < (int)res.size(); i++) {
        if (fun[res[i]] == fun[res[x]]) continue;
        nex.push_back(res[i]);
      }
    } else {
      if (fun[res[x]].parallel(fun[res[y]])) continue;
      point inters = intersection(seg[res[x]], seg[res[y]]);
      for (int i = 0; i < (int)res.size(); i++) {
        if (fun[res[i]].contain(inters)) continue;
        nex.push_back(res[i]);
      }
    }
    if ((int)(res.size() - nex.size()) >= limit) {
      if (x == y)
        ans[dep] = make_pair(res[x], -1);
      else
        ans[dep] = make_pair(res[x], res[y]);
      if (dfs(nex, dep - 1)) {
        return true;
      }
    }
  }
  return false;
}
void solve() {
  static vector<int> res;
  for (int i = 1; i <= n; i++) res.push_back(i);
  if (!dfs(res, k)) printf("NO\n");
}
int main() {
  input();
  solve();
  return 0;
}
