Problem: Problem

There are $ N $ Amidakuji with 3 vertical lines.
No matter which line you start from, the Amidakuji that ends at the starting line is considered a good Amidakuji.
You can select one or more Amidakuji and connect them vertically in any order.
Output "yes" if you can make a good Amidakuji, otherwise output "no".

There are $ w_i $ horizontal lines in the $ i $ th Amidakuji.
$ a_ {i, j} $ indicates whether the $ j $ th horizontal bar from the top of Amidakuji $ i $ extends from the central vertical line to the left or right.
If $ a_ {i, j} $ is 0, it means that it extends to the left, and if it is 1, it means that it extends to the right.

Constraints

The input satisfies the following conditions.

* $ 1 \ le N \ le 50 $
* $ 0 \ le w_i \ le 100 $
* $ a_ {i, j} $ is 0 or 1

Input

The input is given in the following format.


$ N $
$ w_1 $ $ a_ {1,1} $ $ a_ {1,2} $ ... $ a_ {1, w_1} $
$ w_2 $ $ a_ {2,1} $ $ a_ {2,2} $ ... $ a_ {2, w_2} $
...
$ w_N $ $ a_ {N, 1} $ $ a_ {N, 2} $ ... $ a_ {N, w_N} $


All inputs are given as integers.
$ N $ is given on the first line.
$ W_i $ and $ w_i $ $ a_ {i, j} $ are given on the following $ N $ line, separated by blanks.

Output

If you can make a good Amidakuji, it outputs "yes", otherwise it outputs "no".

Examples

Input

3
2 0 0
1 1
5 1 0 0 1 0


Output

yes


Input

2
1 1
1 0


Output

no

Solution (in CPP):

Solution:
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


int N;
int out_table[50][3];
map<int,bool> MAP;
bool FLG;


int makeCode(int code[3]){
	return 100*code[0]+10*code[1]+code[2];
}


void recursive(int code[3],bool used[50]){
	if(FLG)return;
	int tmp_code;

	int next_code[3];

	for(int i = 0; i < N; i++){
		if(used[i] == false){

			for(int k = 0; k < 3; k++){
				next_code[out_table[i][k]] = code[k];
			}

			tmp_code = makeCode(next_code);

			if(tmp_code == 12){
				FLG = true;
				return;
			}
			auto at = MAP.find(tmp_code);
			if(at != MAP.end())continue;
			MAP[tmp_code] = true;

			bool next_used[50];
			for(int k = 0; k < N; k++)next_used[k] = used[k];
			next_used[i] = true;
			recursive(next_code,next_used);
		}
	}

}

int main(){

	scanf("%d",&N);

	int yoko_num,work[3],tmp;

	for(int loop = 0; loop < N; loop++){
		scanf("%d",&yoko_num);

		for(int i = 0; i < 3; i++)work[i] = i;

		for(int i = 0; i < yoko_num; i++){
			scanf("%d",&tmp);
			if(tmp == 0){
				swap(work[0],work[1]);
			}else{
				swap(work[1],work[2]);
			}
		}

		for(int i = 0; i < 3; i++){
			out_table[loop][work[i]] = i;
		}
	}

	FLG = false;
	int first_code[3] = {0,1,2};
	bool first_used[50];
	for(int i = 0; i < N; i++)first_used[i] = false;

	recursive(first_code,first_used);

	if(FLG){
		printf("yes\n");
	}else{
		printf("no\n");
	}

	return 0;
}