#define LL long long
#define double long long
#define eps 1e-8
#define maxn 300
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;
struct Point{
double x,y;
int tp;
Point(){}
Point(double tx,double ty) {x=tx;y=ty;}
bool operator<(const Point& b)const
{
if(x==b.x) return y<b.y;
return x<b.x;
}
}tmp[maxn];
vector p;
struct Line{
Point a,b;
};
int sign(double x)
{
if(!x) return 0;
return x<0? -1:1;
}
double xmul(Point p0,Point p1,Point p2)
{return (p1.x-p0.x)(p2.y-p0.y)-(p2.x-p0.x)(p1.y-p0.y);}
bool is_inline(Point a, Point b, Point c) {
return xmul(a,b,c) == 0;
}
/判两点在线段异侧,点在线段上返回0/
int opposite_side(Point p1,Point p2,Line l)
{
return sign(xmul(p1,l.a,l.b)*xmul(p2,l.a,l.b))<0;
}
int same_side(Point p1,Point p2,Line l)
{
return sign(xmul(p1,l.a,l.b)*xmul(p2,l.a,l.b))>0;
}
/判断两点是否重合/
int equal_point(Point p1,Point p2)
{
return (sign(p1.x-p2.x)0)&&(sign(p1.y-p2.y)0);
}
int vis[200][200];
int main(int argc, char const *argv[])
{
//IN;
int t; cin >> t;
while(t--)
{
int n; scanf("%d", &n);
memset(vis, -1, sizeof(vis));
p.clear(); p.push_back(Point(0,0));
bool flag = 1;
int m = 0;
for(int i=1; i<=n; i++) {
scanf("%lld %lld %d", &tmp[i].x, &tmp[i].y, &tmp[i].tp);
}
//sort(p+1, p+1+n);
/*去重*/
for(int i=1; i<=n; i++) {
if(vis[tmp[i].x][tmp[i].y] == -1) {
vis[tmp[i].x][tmp[i].y] = tmp[i].tp;
p.push_back(tmp[i]);
m++;
} else {
if(vis[tmp[i].x][tmp[i].y] != tmp[i].tp) {
flag = 0;
break;
}
}
}
if(!flag) { /*如果有两类点重叠,无法划分*/
printf("0
");
continue;
}
vector<int> in; /*在直线上的点*/
vector<int> a; /*A类点'o'*/
vector<int> b; /*B类点'x'*/
for(int i=1; i<=m; i++) {
for(int j=i+1; j<=m; j++) {
flag = 1;
Line l; l.a = p[i]; l.b = p[j];
a.clear(); b.clear(); in.clear();
for(int k=1; k<=m; k++) {
if(is_inline(p[i], p[j], p[k])) { /*在直线上*/
in.push_back(k);
continue;
}
if(p[k].tp == 0) {
if(a.empty()) {
a.push_back(k);
if(!b.empty()) {
/*因为只能维护是否在同一边而不能具体到是左边还是右边,所以要判断集合中的第一个点是否违背条件,样例2可以说明这一点*/
if(same_side(p[k],p[b[0]],l)) {
flag = 0;
break;
}
}
} else {
if(opposite_side(p[a[0]],p[k],l)) {
flag = 0;
break;
}
else a.push_back(k);
}
continue;
}
if(p[k].tp == 1) {
if(b.empty()) {
b.push_back(k);
if(!a.empty()) {
if(same_side(p[k],p[a[0]],l)) {
flag = 0;
break;
}
}
} else {
if(opposite_side(p[b[0]],p[k],l)) {
flag = 0;
break;
}
else b.push_back(k);
}
continue;
}
}
if(!flag) continue;
/*对直线上的点判断是否有"间隔出现"的情况*/
sort(in.begin(), in.end());
int sz = in.size();
bool change = 0;
int last = p[in[0]].tp;
for(int k=1; k<sz; k++) {
if(p[in[k]].tp != last) {
if(!change) {
last = p[in[k]].tp;
change = 1;
}
else {
flag = 0;
break;
}
}
}
if(flag) {
//printf("%d %d
", i,j);
goto las;
}
}
}
las:
if(flag) printf("1
");
else printf("0
");
}
return 0;
}