Problem:
Problem G: Color the Map

You were lucky enough to get a map just before entering the legendary magical mystery world.
The map shows the whole area of your planned exploration, including several countries with
complicated borders. The map is clearly drawn, but in sepia ink only; it is hard to recognize at
a glance which region belongs to which country, and this might bring you into severe danger. You
have decided to color the map before entering the area. “A good deal depends on preparation,”
you talked to yourself.

Each country has one or more territories, each of which has a polygonal shape. Territories
belonging to one country may or may not “touch” each other, i.e. there may be disconnected
territories. All the territories belonging to the same country must be assigned the same color.
You can assign the same color to more than one country, but, to avoid confusion, two countries
“adjacent” to each other should be assigned different colors. Two countries are considered to be
“adjacent” if any of their territories share a border of non-zero length.

Write a program that finds the least number of colors required to color the map.

Input

The input consists of multiple map data. Each map data starts with a line containing the total
number of territories n, followed by the data for those territories. n is a positive integer not
more than 100. The data for a territory with m vertices has the following format:

String
x1 y1
x2 y2
...
xm ym
-1

“String” (a sequence of alphanumerical characters) gives the name of the country it belongs to.
A country name has at least one character and never has more than twenty. When a country
has multiple territories, its name appears in each of them.

Remaining lines represent the vertices of the territory. A vertex data line has a pair of nonneg-
ative integers which represent the x- and y-coordinates of a vertex. x- and y-coordinates are
separated by a single space, and y-coordinate is immediately followed by a newline. Edges of
the territory are obtained by connecting vertices given in two adjacent vertex data lines, and byconnecting vertices given in the last and the first vertex data lines. None of x- and y-coordinates
exceeds 1000. Finally, -1 in a line marks the end of vertex data lines. The number of vertices
m does not exceed 100.

You may assume that the contours of polygons are simple, i.e. they do not cross nor touch
themselves. No two polygons share a region of non-zero area. The number of countries in a map
does not exceed 10.

The last map data is followed by a line containing only a zero, marking the end of the input
data.

Output

For each map data, output one line containing the least possible number of colors required to
color the map satisfying the specified conditions.

Sample Input

6
Blizid
0 0
60 0
60 60
0 60
0 50
50 50
50 10
0 10
-1
Blizid
0 10
10 10
10 50
0 50
-1
Windom
10 10
50 10
40 20
20 20
20 40
10 50
-1
Accent
50 10
50 50
35 50
35 25
-1
Pilot
35 25
35 50
10 50
-1
Blizid
20 20
40 20
20 40
-1
4
A1234567890123456789
0 0
0 100
100 100
100 0
-1
B1234567890123456789
100 100
100 200
200 200
200 100
-1
C1234567890123456789
0 100
100 100
100 200
0 200
-1
D123456789012345678
100 0
100 100
200 100
200 0
-1
0

Output for the Sample Input

4
2

Solution in C++ (judge verdict: Wrong Answer)

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<map>
#include<cassert>
#include<cmath>
#define F first
#define S second
#define EPS (1e-10)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> P;
typedef vector<P> VP;
typedef vector<VP> VVP;
int n;
map<string,int> Index;
int index;


int getIndex(string name)
{
  int pos;
  if(Index.find(name) == Index.end())Index[name] = index,pos = index++;
  else pos = Index[name];
  return pos;
}

double dot(P a,P b)
{
  return a.F*b.F+a.S*b.S;
}

double cross(P a,P b)
{
  return a.F*b.S-a.S*b.F;
}

double norm(P a)
{
  return a.F*a.F+a.S*a.S;
}

P operator - (P &a,P &b)
{
  return P(a.F-b.F,a.S-b.S);
}

int ccw(P p0,P p1,P p2)
{
  P a = p1-p0;
  P b = p2-p0;
  if(cross(a,b) > 0)return COUNTER_CLOCKWISE;
  if(cross(a,b) < 0)return CLOCKWISE;
  if(dot(a,b) < 0)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool cmp(const pair<int,int> &a,const pair<int,int> &b)
{
  if(a.first != b.first)return a.first < b.first;
  return a.second < b.second;
}

vector<pair<int,int> > AndrewScan(vector<pair<int,int> > G2)
{
  if(G2.size() < 3)return G2;
  vector<pair<int,int> > U,L;
  sort(G2.begin(),G2.end(),cmp);
  int G2_size = G2.size();

  U.push_back(G2[0]);
  U.push_back(G2[1]);
  L.push_back(G2[G2_size-1]);
  L.push_back(G2[G2_size-2]);

  for(int i=2;i<G2_size;i++)
    {
      for(int j=U.size();j>=2 && ccw(U[j-2],U[j-1],G2[i]) != CLOCKWISE;j--)
	U.pop_back();
      U.push_back(G2[i]);
    }

  for(int i=G2_size-3;i>=0;i--)
    {
      for(int j=L.size();j>=2 && ccw(L[j-2],L[j-1],G2[i]) != CLOCKWISE;j--)
	L.pop_back();
      L.push_back(G2[i]);
    }
  reverse(L.begin(),L.end());
  for(int i=U.size()-2;i>=1;i--)L.push_back(U[i]);
  return L;
}

bool isIntersect(P p1,P p2,P p3,P p4)
{

  return (ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0 &&
	  ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0);
}



int Welch_Powell(vector<vector<int> > &G2)
{

  bool Empti = true;
  for(int i=0;i<G2.size();i++)if(G2[i].size() != 0){Empti = false; break;}
  if(Empti)return 1;
  int G2_size = G2.size();
  int PC = 0;
  int chromatic_number = 0;
  bool Drew[G2_size];
  vector<pair<int,int> > Degree;
  for(int i=0;i<G2_size;i++)Drew[i] = false,Degree.push_back(pair<int,int>(G2[i].size(),i) );
  sort(Degree.begin(),Degree.end(),greater<pair<int,int> >());
  while(PC < G2_size)
    {
      chromatic_number++;
      bool Draw[G2_size];
      for(int i=0;i<G2_size;i++)Draw[i] = Drew[i];
      for(int i=0;i<G2_size;i++)
	{ 
	  if(Draw[Degree[i].second]) 
	    continue;
	  Drew[Degree[i].second] = Draw[Degree[i].second] = true;
	  PC++;
	  int index = Degree[i].second;
	  for(int j=0;j<G2[index].size();j++)Draw[G2[index][j]] = true; 
	}
    }
  return chromatic_number;
}


void printVVI(VVI &G)
{
  cout << "printVVI -- "<< endl;
  for(int i=0;i<G.size();i++)
    {
      for(int j=0;j<G[i].size();j++)
	{
	  cout << G[i][j] << " ";
	}
      cout << endl;
    }
  cout << endl;
}

void printVVP(VVP &G)
{
  cout << "printVVP ---- " << endl;
  for(int i=0;i<G.size();i++)
    {
      for(int j=0;j<G[i].size();j++)
	{
	  cout << "(" << G[i][j].F << "," << G[i][j].S << ") ";
	}
      cout << endl;
    }
  cout << endl;

}

bool isParallel(P a,P b)
{
  return fabs(cross(a,b)-0.0) < EPS;
}

bool isParallel(P a1,P a2,P b1,P b2)
{
  return isParallel(a1-a2,b1-b2);
}

bool Not(P a,P b,P c)
{
  if(ccw(a,b,c) == CLOCKWISE || ccw(a,b,c) == COUNTER_CLOCKWISE)return false;
  return true;
}



bool check(P a,P b,P c,P d)
{
  if(!Not(a,b,c) || !Not(a,b,c))return false;
  if(ccw(a,b,c)== 0 && ccw(a,b,d) == 0)return true;
  if(ccw(a,b,c) == 0 || ccw(a,b,d) == 0)return false;
  return true;
  //if((a == c) && (ccw(a,b,d) == ONLINE_FRONT || ccw(a,b,d) == ON_SEGMENT))return true;
  //if((a == d) && (ccw(a,b,c) == ONLINE_FRONT || ccw(a,b,c) == ON_SEGMENT))return true;
  //if((b == d) && (ccw(a,b,c) == ONLINE_FRONT || ccw(a,b,c) == ON_SEGMENT))return true;
  //if((b == c) && (ccw(a,b,d) == ONLINE_FRONT || ccw(a,b,d) == ON_SEGMENT))return true;
  
  return false;
}

void printP(P p)
{
  cout << "(" << p.F << "," << p.S << ") " << endl;
}

void printCCW(P a,P b,P c)
{
  int res = ccw(a,b,c);
  if(res == 1)cout << "COUNTER_CLOCKWISE" << endl;
  else if(res == -1) cout << "CLOCKWISE" << endl;
  else if(res == 2)cout<< "ONLINE_BACK" << endl;
  else if(res == -2)cout << "ONLINE_FRONT" << endl;
  else cout << "ON_SEGMENT" << endl;  
}


int main()
{

  while(cin >> n,n)
    {
      index = 0;
      Index.clear();
      VVP PG(n);
      vector<string> NameList(n);
      for(int i=0;i<n;i++)
	{
	  cin >> NameList[i];
	 
	  while(true)
	    {
	      P p;
	      cin >> p.first;
	      if(p.first == -1)break;
	      cin >> p.second;
	      PG[i].push_back(p);
	    }
	}


      for(int i=0;i<NameList.size();i++)
	getIndex(NameList[i]);
      VVI G(index);
      for(int i=0;i<n;i++)
	{
	  for(int j=0;j<PG[i].size();j++)
	    {
	      for(int k=0;k<n;k++)
		{
		  if(k == i)continue;
		  int Ikey = getIndex(NameList[i]);
		  int Kkey = getIndex(NameList[k]);
		  if(Ikey == Kkey)continue;

		  for(int l=0;l<PG[k].size();l++)
		    {
		      int kmod = PG[k].size();
		      int imod = PG[i].size();
		      P a,b,c,d;
			  a = PG[i][j];
			  b = PG[i][(j+1)%imod];
			  c = PG[k][l];
			  d = PG[k][(l+1)%kmod];
		  
			  if(isIntersect(a,b,c,d) && isParallel(a,b,c,d) && check(a,b,c,d))
			    {
			      //cout << "OK! "<< Ikey << ".pb " << Kkey << endl;
			      //printP(a);printP(b);printP(c); printP(d);
			      //cout << "ccw(a,b,c) = ";
			      //printCCW(a,b,c);
			      //cout << "ccw(a,b,d) = ";
			      //printCCW(a,b,d);
			      if(Ikey >= G.size())
				{
				  G.push_back(vector<int>());				 
				  G[Ikey].push_back(Kkey);
				}
			      else
				G[Ikey].push_back(Kkey);
			      
			      break;
			    }
		    }
		}
	    }
	}
      
   
      for(int i=0;i<G.size();i++)
	    {
	      sort(G[i].begin(),G[i].end());
	      G[i].erase(unique(G[i].begin(),G[i].end()),G[i].end());
	    }
	
     
      //printVVI(G);
      cout << Welch_Powell(G) << endl;

    }
  return 0;
}