#include <bits/stdc++.h>
using namespace std;
const long double pi = 3.1415926535897932384626433832795l;
template <typename T>
inline auto sqr(T x) -> decltype(x * x) {
  return x * x;
}
template <typename T1, typename T2>
inline bool umx(T1& a, T2 b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T1, typename T2>
inline bool umn(T1& a, T2 b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
struct Input {
  int n;
  vector<tuple<int, int, int> > q;
  bool read() {
    if (scanf("%d", &n) != 1) {
      return 0;
    }
    q.resize(4 * n);
    for (int i = int(0); i < int(4 * n); ++i) {
      int a, b, c;
      scanf("%d%d%d", &a, &b, &c);
      --a, --b, --c;
      q[i] = make_tuple(a, b, c);
    }
    return 1;
  }
  void init(const Input& input) { *this = input; }
};
const tuple<int, int, int> t1 = make_tuple(0, 1, 1), t2 = make_tuple(1, 0, 0);
const vector<tuple<int, int, int> > cq = {t1, t1, t1, t1, t2, t2, t2, t2};
struct Data : Input {
  vector<int> ans;
  vector<int> cnt;
  void write() {
    cnt.assign(n, 4);
    for (int x : ans) {
      int a, b, c;
      tie(a, b, c) = q[x];
      assert(cnt[a] > 0);
      cnt[a]--;
      assert(cnt[b] < 9);
      cnt[b]++;
      assert(cnt[c] < 9);
      cnt[c]++;
    };
    puts("YES");
    for (int x : ans) {
      printf("%d ", x + 1);
    }
    printf("\n");
  }
  virtual void solve() {}
  virtual void clear() { *this = Data(); }
};
struct Solution : Data {
  vector<map<int, int> > g;
  vector<vector<int> > qid;
  vector<int> cycle;
  vector<int> used;
  vector<int> start;
  void dec(int from, int to) {
    g[from][to]--;
    if (!g[from][to]) {
      g[from].erase(to);
    }
  }
  void dfs(int x) {
    while (!g[x].empty()) {
      int to = g[x].begin()->first;
      dec(x, to);
      dec(to, x);
      dfs(to);
    }
    cycle.push_back(x);
  }
  void find_ans(int x) {
    if (qid[x].empty()) return;
    ;
    int cur_q = qid[x].back() - n;
    qid[x].pop_back();
    int b, c;
    tie(ignore, b, c) = q[cur_q];
    assert(start[cur_q] == b || start[cur_q] == c);
    if (start[cur_q] == c) swap(b, c);
    ans.push_back(cur_q);
    find_ans(c);
  }
  void solve() {
    g.resize(5 * n);
    qid.resize(n);
    start.assign(4 * n, -1);
    for (int i = int(0); i < int(4 * n); ++i) {
      int a, b, c;
      tie(a, b, c) = q[i];
      qid[a].push_back(n + i);
      g[b][n + i]++;
      g[c][n + i]++;
      g[n + i][b]++;
      g[n + i][c]++;
    }
    used.assign(5 * n, 0);
    cycle.clear();
    for (int i = int(0); i < int(n); ++i) {
      if (!g[i].empty()) {
        dfs(i);
      }
    };
    int prev = -1;
    for (int x : cycle) {
      if (x >= n) {
        assert(prev >= 0 && prev < n);
        start[x - n] = prev;
      }
      prev = x;
    }
    for (int i = int(0); i < int(n); ++i) {
      while (!qid[i].empty()) {
        find_ans(i);
      }
    }
  }
  void clear() { *this = Solution(); }
};
Solution sol;
int main() {
  cout.setf(ios::showpoint | ios::fixed);
  cout.precision(20);
  sol.read();
  sol.solve();
  sol.write();
  return 0;
}
