#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

const int dy[2][3] = {-1,0,0,1,0,0};
const int dx[2][3] = {0,-1,1,0,-1,1};

struct Tetra {
  bool d;
  /*
    d=0:    d=1:
    a1△a2    a0
      a0    a1▽a2
   */
  int b;
  int a0,a1,a2;
  int x, y;
  Tetra(int b, int a0, int a1, int a2, int x, int y) :
    b(b),a0(a0),a1(a1),a2(a2),x(x),y(y) {
    d = (x+y&1);
  }
  void rotate(int &a, int &b, int &c, int &d) {
    int t=a; a=b;b=c;c=d;d=t;
  }
  void roll(int dir) {
    if (dir == 0) swap(a0,b);              // y
    else if (dir == 1) rotate(b,a2,a0,a1); // +x
    else rotate(b,a1,a0,a2);               // -x
    y += dy[d][dir];
    x += dx[d][dir];    
    d = !d;
  }
  bool operator<(const Tetra &rhs) const {
    return pii(x,y) < pii(rhs.x,rhs.y);
  }
};

vector<pii> lastOne(const vector<int> &xs, const vector<int> &ys) {
  set<pii> ps,neighbor;
  REP(i,3) {
    ps.insert(pii(ys[i],xs[i]));
    bool d = xs[i]+ys[i]&1;
    REP(j,3) {
      int yy = ys[i]+dy[d][j];
      int xx = xs[i]+dx[d][j];
      neighbor.insert(pii(yy,xx));
    }
  }
  
  vector<pii> res;
  FOR(it, neighbor) {
    set<pii> tps = ps;
    tps.insert(pii(it->first,it->second));    

    Tetra ini(0,1,2,3,xs[0],ys[0]);
    queue<Tetra> Q;
    set<pii> visited;
    Q.push(ini);
    visited.insert(pii(ys[0],xs[0]));
    set<int> bs;
    while(!Q.empty()) {
      Tetra p = Q.front(); Q.pop();
      bs.insert(p.b);
      REP(i,3) {
        Tetra nxt = p;
        nxt.roll(i);
        if (!visited.count(pii(nxt.y,nxt.x)) && tps.count(pii(nxt.y, nxt.x))) {
          Q.push(nxt);
          visited.insert(pii(nxt.y, nxt.x));
        }
      }
    }
    if (bs.size() == 4) {
      res.push_back(*it);
    }
  }
  return res;
}

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
  Edge(int src, int dst) : src(src), dst(dst) {}
};

bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

bool valid[50000];

bool augment(const Graph& g, int u,
    vector<int>& matchTo, vector<bool>& visited) {
  if (u < 0) return true;
  FOR(e, g[u]) if (!visited[e->dst] && valid[e->dst]) {
    visited[e->dst] = true;
    if (augment(g, matchTo[e->dst], matchTo, visited)) {
      matchTo[e->src] = e->dst;
      matchTo[e->dst] = e->src;
      return true;
    }
  }
  return false;
}

int bipartiteMatching(const Graph& g, int L, vector<int> &matchTo) {
  const int n = g.size();
  int match = 0;
  REP(u, L) {
    if (!valid[u] || matchTo[u] != -1) continue;
    vector<bool> visited(n);
    if (augment(g, u, matchTo, visited)) ++match;
  }
  return match;
}


int main() {
  int n;
  while(cin >> n, n) {
    vector<vector<int> > xss,yss;
    vector<vector<pii> > vs;
    map<pii,int> mp;
    int num = 0;
    REP(i,n) {
      vector<int> xs,ys;
      REP(j,3) {
        int x,y;
        cin >> x  >> y;
        xs.push_back(x);
        ys.push_back(y);
      }
      xss.push_back(xs);
      yss.push_back(ys);
      vector<pii> v = lastOne(xs,ys);
      vs.push_back(v);
      FOR(it, v) if (mp.count(*it) == 0) mp[*it] = num++;
      // cout << i << " : ";
      // FOR(it, v) printf("(%d,%d) ", it->second, it->first);
      // cout << endl;
    }
    Graph g(n+num);
    REP(i,n+num) valid[i] = 1;
    REP(i, n) {
      FOR(jt, vs[i]) {
        int dst = n+mp[*jt];
        g[i].push_back(Edge(i,dst,1));
        g[dst].push_back(Edge(dst,i,1));
      }
      REP(j,3) {
        pii p(yss[i][j], xss[i][j]);
        if (mp.count(p)) {
          valid[n+mp[p]] = 0;
        }
      }
    }
    vector<int> allMatchTo(g.size(), -1);
    int allMatch = bipartiteMatching(g,n,allMatchTo);
    if (allMatch == n) {
      puts("Valid");
      continue;
    } else if (allMatch < n-4) {
      puts("Invalid");
      continue;
    }
    vector<int> ans;
    REP(i,n) {
      vector<int> matchTo = allMatchTo;
      int match = allMatch;
      
      int dst = matchTo[i];
      if (dst != -1) {
        matchTo[i] = matchTo[dst] = -1;
        match--;
      }
      REP(j,3) {
        pii p(yss[i][j], xss[i][j]);
        if (mp.count(p)) {
          valid[n+mp[p]] = 1;
        }
      }
      valid[i] = 0;

      // cout << allMatch << " " << match << " ";
      match += bipartiteMatching(g,n,matchTo);
      if (match == n-1) {
        ans.push_back(i);
      }
      // cout << match << endl;
      // 戻す
      if (dst != -1) {
        matchTo[i] = dst;
        matchTo[dst] = i;
      }
      REP(j,3) {
        pii p(yss[i][j], xss[i][j]);
        if (mp.count(p)) {
          valid[n+mp[p]] = 0;
        }
      }
      valid[i] = 1;      
    }
    if (ans.size()) {
      puts("Remove");
      FOR(it, ans) cout << *it+1 << endl;
    }else {
      puts("Invalid");
    }
  }
}

Measured memory_bytes: 4588