Problem:
秋のイルミネーション

四角形が大好きな人が多く住む四角町では、四角形の電光板を組み合わせたイルミネーションで町中を彩るお祭りが開催されます。この電光板は電気を流すと発光し、発光している板に接している板も発光します。したがって、電光板を何枚使っても、すべてがひとかたまりに接していれば電源がひとつで済むという優れものです。

お祭り実行委員会では、四角形を組み合わせたデザインを町民から募集し多数のイルミネーションを作成します。各イルミネーションは、デザインを構成する四角形の配置によって必要となる電源の個数が変わるため、必要な電源の個数を把握する作業に大きな手間がかかります。そこで、あなたは四角形の配置を調べ、必要な電源の個数を計算するプログラムを作成して実行委員会を手助けすることにしました。

イルミネーションの個数、各イルミネーションを構成する四角形の情報を入力とし、イルミネーションごとに必要な電源の個数を出力するプログラムを作成してください。重なっていたり接していたりする四角形を 1 つのまとまりと考え、1 つのまとまりに対して電源の個数は 1 つと数えてください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。各データセットは以下の形式で与えられます。

N
M1
xa1 ya1 xb1 yb1 xc1 yc1 xd1 yd1
xa2 ya2 xb2 yb2 xc2 yc2 xd2 yd2
:
xaM1 yaM1 xbM1 ybM1 xcM1 ycM1 xdM1 ydM1
M2
:
:
MN
:
:

1 行目にイルミネーションの個数 N (1 ≤ N ≤ 100) が与えられます。続いて、N 個のイルミネーションの情報が与えられます。第 i のイルミネーションの情報として、イルミネーションを構成する四角形の個数 Mi (1 ≤ Mi ≤ 100) が１行に与えられます。続く Mi 行に j 個目の四角形の頂点 xaj, yaj, xbj, ybj, xcj, ycj, xdj, ydj (-1000 以上 1000 以下の整数) が与えられます。

入力される四角形の頂点座標は、時計回りの順に従って入力されます。ただし、入力データの四角形はすべて凸な四角形とします。

データセットの数は 10 を超えません。

Output

入力データセットごとに、イルミネーションごとに必要な電源の個数を出力します。出力する電源の個数は各イルミネーションが入力された順番に従ってください。

Sample Input

3
1
0 0 0 1 1 1 1 0
2
0 0 0 1 1 1 1 0
100 100 100 200 200 200 200 100
2
0 0 0 100 100 100 100 0
10 10 10 20 20 20 20 10
2
1
30 40 40 50 40 20 20 10
1
30 40 40 50 40 20 20 10
0

Output for the Sample Input

1
2
1
1
1

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.*;
public class Main
{
    static boolean used[];
    static Point rec[][];
    static double EPS=1e-5;
    public static void main(String[] args) 
    {
        Scanner in=new Scanner(System.in);
        for(;;)
        {
            int N=in.nextInt();
            if(N==0)
                return;
            while(N-->0)
            {
                int n=in.nextInt();
                rec=new Point[n][4];
                used=new boolean[n];// true is used...
                for(int i=0;i<n;i++)
                    for(int j=0;j<4;j++)
                        rec[i][j]=new Point(in.nextDouble(), in.nextDouble());
 
                int cnt=0;
                for(int i=0;i<n;i++)
                {
                    if(!used[i])
                    {
                        ++cnt;
                        dfs(i);
                    }
                }
                System.out.println(cnt);
            }
        }
    }
 
    static void dfs(int now)
    {
        used[now]=true;
        for(int i=0;i<used.length;i++)
        {
            if(!used[i])
            {
                boolean go=false;
                //交差判定(境界含む)
                for(int j=0;j<4;j++)
                    for(int k=0;k<4;k++)
                    {
                        if(Point.lineCross(rec[now][j], rec[now][(j+1)%4],rec[i][k] , rec[i][(k+1)%4]))
                            go=true;    
                    }
                for(int k=0;k<4;k++)
                {
                    if(Point.ccw(rec[now][0],rec[i][k],rec[now][1])==1&&Point.ccw(rec[now][1],rec[i][k],rec[now][2])==1&&
                            Point.ccw(rec[now][2],rec[i][k],rec[now][3])==1&&Point.ccw(rec[now][3],rec[i][k],rec[now][0])==1
                            ||Point.ccw(rec[now][0],rec[i][k],rec[now][1])==-1&&Point.ccw(rec[now][1],rec[i][k],rec[now][2])==-1&&
                            Point.ccw(rec[now][2],rec[i][k],rec[now][3])==-1&&Point.ccw(rec[now][3],rec[i][k],rec[now][0])==-1)
                        go=true;
                }


 for(int k=0;k<4;k++)
                {
                    if(Point.ccw(rec[i][0],rec[now][k],rec[i][1])==1&&Point.ccw(rec[i][1],rec[now][k],rec[i][2])==1&&
                            Point.ccw(rec[i][2],rec[now][k],rec[i][3])==1&&Point.ccw(rec[i][3],rec[now][k],rec[i][0])==1
                            ||Point.ccw(rec[i][0],rec[now][k],rec[i][1])==-1&&Point.ccw(rec[i][1],rec[now][k],rec[i][2])==-1&&
                            Point.ccw(rec[i][2],rec[now][k],rec[i][3])==-1&&Point.ccw(rec[i][3],rec[now][k],rec[i][0])==-1)
                        go=true;
                }









                if(go)
                    dfs(i);
            }
        }
    }
    static public void debug(Object... o)
    {
        System.err.println(Arrays.deepToString(o));
    }
}
 
class Point
{
    double x;
    double y;
    static double EPS=1e-5;
    Point(double x,double y)
    {
        this.x=x;
        this.y=y;
    }
 
    //線分p1-p2と線分p3-p4が交差しているかを判定 true->交差(=含みで接する含む) false->交差せず
    static boolean lineCross(Point p1,Point p2,Point p3,Point p4)
    {
        double a=(p1.x-p2.x)*(p3.y-p1.y)+(p1.y-p2.y)*(p1.x-p3.x);
        double b=(p1.x-p2.x)*(p4.y-p1.y)+(p1.y-p2.y)*(p1.x-p4.x);
        double c=(p3.x-p4.x)*(p1.y-p3.y)+(p3.y-p4.y)*(p3.x-p1.x);
        double d=(p3.x-p4.x)*(p2.y-p3.y)+(p3.y-p4.y)*(p3.x-p2.x);
        return a*b<=EPS && c*d<=EPS;
    }
 
    //counterClockWise p1->p2->p3が反時計周りなら1 時計周りなら-1を返す 
    static double ccw(Point p1,Point p2,Point p3)
    {
        Point a=new Point(p2.x-p1.x, p2.y-p1.y);
        Point b=new Point(p3.x-p1.x, p3.y-p1.y);
        if(crossProduct(a, b)>=-EPS) return 1;//counter clockwise
        if(crossProduct(a, b)<=EPS) return -1;//clockwise
        else return 0;
    }
    //外積
    static double crossProduct(Point a,Point b)
    {
        return a.x*b.y-a.y*b.x;
    }
 
    //3頂点からなる三角形の面積
    static double triangleArea(Point p1,Point p2,Point p3)
    {
        return Math.abs((p3.y-p1.y)*(p2.x-p1.x)-(p2.y-p1.y)*(p3.x-p1.x))/2;
    }
}
 
//x>=yの優先度で頂点を昇順ソート
//Arrays.sort(p,new PointComparator());こんな感じで使う
class PointComparator implements Comparator<Point>
{
    public int compare(Point p1,Point p2)
    {
        double cmp=p1.x-p2.x;
        if(cmp==0)
            cmp=p1.y-p2.y;
        if(cmp<0)
            cmp=-1;
        else
            cmp=1;
        return (int) cmp;
    }
}