#include <bits/stdc++.h>
using namespace std;
template <typename T>
void unique(vector<T> &u) {
  sort(u.begin(), u.end());
  u.resize(unique(u.begin(), u.end()) - u.begin());
}
template <typename T>
void debug_out(T t) {
  cerr << t;
}
template <typename A, typename B>
void debug_out(pair<A, B> u) {
  cerr << "(" << u.first << " " << u.second << ")";
}
template <typename T>
void debug_out(vector<T> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1) cerr << ", ";
  }
}
template <typename T>
void debug_out(vector<vector<T>> t) {
  int sz = t.size();
  for (int i = 0; i < sz; i++) {
    debug_out(t[i]);
    if (i != sz - 1) cerr << endl;
  }
}
class dsu {
 public:
  vector<int> p;
  int n;
  dsu(int _n) : n(_n) {
    p.resize(n);
    iota(p.begin(), p.end(), 0);
  }
  inline int get(int x) { return (x == p[x] ? x : (p[x] = get(p[x]))); }
  inline bool unite(int x, int y) {
    x = get(x);
    y = get(y);
    if (x != y) {
      p[x] = y;
      return true;
    }
    return false;
  }
};
struct point {
  int x, y, id = -1;
  point(){};
  point(int _x, int _y) : x(_x), y(_y){};
  bool operator<(const point &a) const { return id > a.id; }
  bool operator==(const point &a) const { return x == a.x && y == a.y; }
};
vector<int> dx = {0, 1, 1, 1, 0, -1, -1, -1};
vector<int> dy = {1, 1, 0, -1, -1, -1, 0, 1};
point sp(point a, int id) { return point(a.x + dx[id], a.y + dy[id]); }
long long dis(point a) { return 1LL * a.x * INT_MAX + a.y; }
int n, t;
int main() {
  scanf("%d%d", &n, &t);
  vector<point> a(n);
  for (int i = 0; i < n; i++) {
    scanf("%d%d", &a[i].x, &a[i].y);
    a[i].id = i;
  }
  sort(a.begin(), a.end(), [&](point u, point v) {
    return make_pair(u.x, u.y) < make_pair(v.x, v.y);
  });
  vector<vector<int>> edges(n, vector<int>(8, -1));
  dsu ss(n);
  int l = 0, r = 0;
  for (int i = 0; i < n; i++) {
    if (i < n - 1 && a[i].x == a[i + 1].x && a[i].y == a[i + 1].y - 1) {
      edges[a[i].id][0] = a[i + 1].id;
      edges[a[i + 1].id][4] = a[i].id;
      ss.unite(a[i].id, a[i + 1].id);
    }
    while (r < n &&
           make_pair(a[r].x, a[r].y) <= make_pair(a[i].x + 1, a[i].y + 1))
      r++;
    while (l < n &&
           make_pair(a[l].x, a[l].y) < make_pair(a[i].x + 1, a[i].y - 1))
      l++;
    for (int j = l; j < r; j++) {
      int dif = a[j].y - a[i].y;
      int id;
      if (!dif)
        id = 2;
      else
        id = (dif > 0 ? 1 : 3);
      edges[a[i].id][id] = a[j].id;
      edges[a[j].id][(id + 4) % 8] = a[i].id;
      ss.unite(a[i].id, a[j].id);
    }
  }
  for (int i = 0; i < n; i++)
    if (ss.get(i) != ss.get(0)) {
      printf("NO");
      return 0;
    }
  sort(a.begin(), a.end());
  reverse(a.begin(), a.end());
  printf("YES\n");
  dsu st(4 * n + 1);
  auto it = max_element(a.begin(), a.end(),
                        [&](point a, point b) { return a.y < b.y; });
  st.unite(4 * n, 4 * it->id);
  unordered_map<long long, vector<int>> dog;
  for (auto u : a) {
    for (int i = 0; i < 8; i += 2) {
      int v = edges[u.id][i];
      if (v == -1) dog[dis(sp(u, i))].push_back(4 * u.id + i / 2);
    }
  }
  for (auto u : a) {
    vector<int> xs(8);
    for (int i = 0; i < 8; i++) xs[i] = edges[u.id][i] >= 0;
    for (int i = 1; i < 8; i += 2) {
      if (!xs[i] && !xs[i - 1] && !xs[(i + 1) % 8])
        st.unite(4 * u.id + i / 2, 4 * u.id + ((i + 1) % 8) / 2);
    }
  }
  for (auto u : dog) {
    point cc = point(u.first / INT_MAX, u.first % INT_MAX);
    vector<int> id = u.second;
    for (auto i : id) st.unite(i, id.front());
    for (int i = 0; i < 8; i += 2) {
      if (dog.count(dis(sp(cc, i)))) st.unite(id[0], dog[dis(sp(cc, i))][0]);
    }
  }
  vector<int> alive(n, 1);
  int iter = 0;
  vector<int> pp(4 * n + 1);
  auto valid = [&](point v) {
    iter++;
    bool ok = false;
    for (int i = 0; i < 8; i++) {
      if (~edges[v.id][i] && alive[edges[v.id][i]]) {
        int xs = 8;
        i++;
        if (i == 8) i = 0;
        vector<int> pc;
        while (xs--) {
          if (~edges[v.id][i] && alive[edges[v.id][i]]) {
            for (auto j : pc) {
              if (pp[j] == iter) return false;
            }
            for (auto j : pc) pp[j] = iter;
            pc.clear();
          } else if (i % 2 == 0) {
            pc.push_back(st.get(4 * v.id + i / 2));
            ok |= st.get(4 * v.id + i / 2) == st.get(4 * n);
          }
          i++;
          if (i == 8) i = 0;
        }
        break;
      }
      ok |= i == 7;
    }
    return ok;
  };
  set<point> pos;
  for (int i = 0; i < n; i++)
    if (valid(a[i])) pos.insert(a[i]);
  vector<vector<int>> in(4 * n + 1);
  for (int i = 0; i < 4 * n + 1; i++) in[st.get(i)].push_back(i);
  vector<int> res;
  int cnt = 0;
  vector<int> ap(n);
  while (pos.size()) {
    cnt++;
    res.push_back(pos.begin()->id);
    point cc = *pos.begin();
    pos.erase(pos.begin());
    alive[cc.id] = 0;
    vector<int> id, _id;
    for (int i = 0; i < 8; i++) {
      if (~edges[cc.id][i] && alive[edges[cc.id][i]])
        id.push_back(edges[cc.id][i]);
    }
    for (int i = 0; i < 8; i += 2) {
      if (edges[cc.id][i] == -1 || !alive[edges[cc.id][i]]) {
        if (st.get(4 * n) != st.get(4 * cc.id + i / 2))
          _id.push_back(st.get(4 * cc.id + i / 2));
      }
    }
    unique(_id);
    for (auto i : _id) {
      for (auto j : in[i]) id.push_back(j / 4);
    }
    unique(id);
    for (int i = 0; i < 8; i += 2) {
      if (edges[cc.id][i] == -1 || !alive[edges[cc.id][i]]) {
        st.unite(4 * cc.id + i / 2, 4 * n);
      }
    }
    for (int i = 0; i < 8; i += 2) {
      if (~edges[cc.id][i] && alive[edges[cc.id][i]]) {
        int v = edges[cc.id][i];
        st.unite(4 * v + ((i + 4) % 8) / 2, 4 * n);
      }
    }
    for (auto i : id) {
      if (ap[i] == cnt) continue;
      ap[i] = cnt;
      if (alive[i] && valid(a[i]))
        pos.insert(a[i]);
      else
        pos.erase(a[i]);
    }
  }
  reverse(res.begin(), res.end());
  for (auto i : res) printf("%d\n", i + 1);
  return 0;
}
