#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <cassert>
#include <string>
#include <memory.h>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <set>
#include <map>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <cctype>
#include <fstream>
#include <complex>
#include <cmath>
using namespace std;

#define REP2(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define ITER(c) __typeof((c).begin())
#define PB(e) push_back(e)
#define FOREACH(i, c) for(ITER(c) i = (c).begin(); i != (c).end(); ++i)
#define MP(a, b) make_pair(a, b)
#define PARITY(n) ((n) & 1)

typedef long long ll;
typedef complex<double> xy_t;
typedef pair<xy_t, xy_t> L;
typedef vector<xy_t> polygon;

const int INF = 1000 * 1000 * 1000 + 7;
const double EPS = 1e-6;

#define EQ(a, b) (abs((a) - (b)) < EPS)
#define DI(l) ((l).second-(l).first)
#define CCW(l, a) ccw((l).first, (l).second, (a))

double cross(const xy_t &a, const xy_t &b) { return imag(conj(a)*b); }
double dot(const xy_t& a, const xy_t& b) { return real(conj(a)*b); }

int ccw(xy_t a, xy_t b, xy_t c) {
	double d = cross(b -= a, c -= a);
	return d>EPS ? 1 : d<-EPS ? -1 : dot(b,c)<-EPS ? 2 : norm(b)+EPS<norm(c) ? -2 : 0;
}

bool parallel(const L &l, const L &m) { return EQ(cross(DI(l), DI(m)), 0); }
bool sameline(const L &l, const L &m) { return parallel(l, m) && EQ(cross(DI(l), m.second-l.first), 0); }

bool intersectSS(const L &s, const L &t) {
  return CCW(s,t.first)*CCW(s,t.second)<=0 && CCW(t,s.first)*CCW(t,s.second)<=0;
}

bool share_border(const polygon &p1, const polygon &p2){
  int n = p1.size();
  int m = p2.size();
  REP(i, n)REP(j, m){
    L l1 = L(p1[i], p1[(i+1)%n]);
    L l2 = L(p2[j], p2[(j+1)%m]);
    if(sameline(l1, l2) && intersectSS(l1, l2)){
      if(p1[i].real() == p2[j].real()){
      	vector<double> ys;
      	ys.push_back(l1.first.imag());
      	ys.push_back(l2.first.imag());
      	ys.push_back(l1.second.imag());
      	ys.push_back(l2.second.imag());
      	sort(ALL(ys));
      	if(ys[2] - ys[1] > EPS) return true;
      }else{
      	vector<double> xs;
      	xs.push_back(l1.first.real());
      	xs.push_back(l2.first.real());
      	xs.push_back(l1.second.real());
      	xs.push_back(l2.second.real());
      	sort(ALL(xs));
      	if(xs[2] - xs[1] > EPS) return true;
      }
    }
  } 
  return false;
}


int dfs(int v, const vector<vector<bool> > &g, vector<int> &color, int M){
  int n = g.size();
  if(v == n) return M + 1;

  int res = INF;
  REP(c, M + 2){
    bool ok = true;
    REP(i, v) if(g[v][i] && color[i] == c) ok = false;
    
    if(ok){
      color[v] = c;
      res = min(res, dfs(v + 1, g, color, max(M, c)));
      color[v] = -1;
    }
  }
  return res;
}

int main(){
  int n;
  
  while(cin >> n && n > 0){
    vector<string> names(n);
    map<string, int> ID;
    vector<polygon> polys(n);
    
    REP(i, n){
      cin >> names[i];
      
      if(ID.find(names[i]) == ID.end()){
	int count = ID.size();
	ID[names[i]] = count;
      }
      int x, y;
      while(cin >> x && x != -1 && cin >> y){
	polys[i].PB(xy_t(x, y));
      }
    }

    int c_size = ID.size();
    vector<vector<bool> > g(c_size,vector<bool>(c_size,false));
    
    REP(i, n)REP(j, i)if(share_border(polys[i], polys[j])){
      g[ID[names[i]]][ID[names[j]]] = true;
      g[ID[names[j]]][ID[names[i]]] = true;      
    }


    vector<int> color(c_size, -1);
    cout << dfs(0, g, color, -1) << endl;
  }
  return 0;
}

Measured memory_bytes: 1288