#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <cstring>

using namespace std;

const int MAX_N = 5000;

int coord[2][16][6] = {
	// 偶数グリッド用
	{
		{-1, 0, 1, 0, 0, -1},
		{-1, -1, 0, -1, 1, -1},
		{-2, 0, -1, 0, -1, 1},
		{1, 1, 1, 0, 2, 0},
		{-1, -2, -1, -1, 0, -1},
		{-1, -1, 0, -1, 1, 0},
		{0, -1, 1, 0, 1, 1},
		{1, 0, 1, 1, 2, 1},
		{1, -2, 1, -1, 0, -1},
		{1, -1, 0, -1, -1, 0},
		{0, -1, -1, 0, -1, 1},
		{-1, 0, -1, 1, -2, 1},
		{-3, 0, -2, 0, -1, 0},
		{-2, 0, -1, 0, 1, 0},
		{-1, 0, 1, 0, 2, 0},
		{1, 0, 2, 0, 3, 0}
	},
	// 奇数グリッド用
	{
		{0, 1, -1, 0, 1, 0},
		{-1, 1, 0, 1, 1, 1},
		{-2, 0, -1, 0, -1, -1},
		{1, -1, 1, 0, 2, 0},
		{-2, -1, -1, -1, -1, 0},
		{-1, -1, -1, 0, 0, 1},
		{-1, 0, 0, 1, 1, 1},
		{0, 1, 1, 1, 1, 2},
		{2, -1, 1, -1, 1, 0},
		{1, -1, 1, 0, 0, 1},
		{1, 0, 0, 1, -1, 1},
		{0, 1, -1, 1, -1, 2},
		{-3, 0, -2, 0, -1, 0},
		{-2, 0, -1, 0, 1, 0},
		{-1, 0, 1, 0, 2, 0},
		{1, 0, 2, 0, 3, 0}
	}
};

bool search(const vector< vector<int> >& g, vector<int>& match, vector<int>& visit, int u){
	if(u == -2) return false; // 使用できない頂点
	if(u == -1) return true;
	for(int i=0;i<g[u].size();i++){
		int next = g[u][i];
		if(visit[next]) continue;
		visit[next] = true;
		if(search(g, match, visit, match[next])){
			match[u] = next, match[next] = u;
			return true;
		}
	}
	return false;
}

int main(){
	int n;
	int x[3*MAX_N], y[3*MAX_N];
	while(cin >> n && n){
		vector< vector<int> > g(n);
		vector< pair<int, int> > nodeCoord;
		map< pair<int, int>, int > nodeIdx;
		set< pair<int, int> > tetraIdx;

		for(int i=0;i<n;i++){
			for(int j=0;j<3;j++){
				cin >> x[3*i+j] >> y[3*i+j];
				tetraIdx.insert(make_pair(x[3*i+j], y[3*i+j]));
			}
		}

		// 各正四面体の最後の一面の位置の候補を列挙する
		for(int i=0;i<n;i++){
			int type = (abs(x[3*i])+abs(y[3*i]))%2;
			for(int j=0;j<16;j++){
				int useID = -1;
				for(int k=0;k<3;k++){
					int cx = x[3*i]+coord[type][j][2*k  ];
					int cy = y[3*i]+coord[type][j][2*k+1];
					if((cx != x[3*i+1] || cy != y[3*i+1]) && (cx != x[3*i+2] || cy != y[3*i+2])){
						if(useID == -1) useID = k;
						else if(useID >= 0) useID = -2;
					}
				}
				if(useID >= 0){
					int cx = x[3*i]+coord[type][j][2*useID  ];
					int cy = y[3*i]+coord[type][j][2*useID+1];
					if(!nodeIdx.count(make_pair(cx, cy))){
						int newIdx = g.size();
						nodeCoord.push_back(make_pair(cx, cy));
						nodeIdx[make_pair(cx, cy)] = newIdx;
						g.push_back(vector<int>());
					}
					int idx = nodeIdx[make_pair(cx, cy)];
					g[i].push_back(idx);
					g[idx].push_back(i);
				}
			}
		}

		vector<int> match(g.size(), -1);

		// 各正四面体で指定されているグリッドを使用禁止にする
		for(int i=0;i<nodeCoord.size();i++){
			if(tetraIdx.count(nodeCoord[i])){
				match[n+i] = -2;
			}
		}

		int curMatch = 0;
		vector<int> visit;
		for(int i=0;i<n;i++){
			visit.assign(g.size(), 0);
			curMatch += search(g, match, visit, i);
		}

		if(curMatch == n) cout << "Valid" << endl;
		else {
			vector<int> matchCopy = match;
			vector<int> checkIdx, removeIdx;
			for(int i=0;i<n;i++)
				if(match[i] == -1) checkIdx.push_back(i);

			// 最初の時点でマッチしなかった頂点が5以上ある場合は調べなくて良い．
			if(checkIdx.size() <= 4){
				for(int i=0;i<n;i++){
					int matchSize = curMatch;
					match = matchCopy;
					for(int j=0;j<3;j++){
						if(nodeIdx.count(make_pair(x[3*i+j], y[3*i+j])))
							match[nodeIdx[make_pair(x[3*i+j], y[3*i+j])]] = -1;
					}
					if(match[i] != -1){
						match[match[i]] = -1;
						match[i] = -2;
						matchSize--;
					}
					for(int j=0;j<checkIdx.size();j++){
						if(checkIdx[j] == i) continue;
						visit.assign(g.size(), 0);
						matchSize += search(g, match, visit, checkIdx[j]);
					}
					if(matchSize == n-1) removeIdx.push_back(i);
				}
			}
			if(removeIdx.empty()) cout << "Invalid" << endl;
			else {
				cout << "Remove" << endl;
				for(int i=0;i<removeIdx.size();i++)
					cout << removeIdx[i]+1 << endl;
			}
		}
	}
}

Measured memory_bytes: 4828