unittest
{
	assert( [ "4 6", "3 1 2 3", "2 4 2", "2 4 6", "1 6" ].parse.expand.solve == "YES" );
	assert( [ "4 4", "2 1 2", "2 1 2", "1 3", "2 4 3" ].parse.expand.solve == "NO" );
}



import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto nm = input.front.split.to!( long[] );
	auto lss = new long[][ nm[ 0 ] ];
	foreach( ref ls; lss )
	{
		input.popFront;
		auto kls = input.front.split.to!( long[] );
		ls = kls[ 1 .. $ ];
	}
	return tuple( nm[ 1 ], lss );
}

auto solve( long m, long[][] lss )
{
	// 人と言語でグループを構成
	auto uft = UnionFindTree( lss.length + m );
	foreach( i, ls; lss )
	{
		foreach( l; ls )
		{
			uft.unite( i, lss.length - 1 + l );
		}
	}
	
	// 全員が同じグループに属しているか（＝コミュニケーションを取れるか）を判定
	foreach( i; 1L .. lss.length )
	{
		if( !uft.same( 0, i ) ) return "NO";
	}
	return "YES";
}

// UnionFind木
struct UnionFindTree
{
	private long[] ps;
	private long[] rs;
	
	public this( long n )
	{
		ps.length = n;
		ps[] = -1;
		rs.length = n;
	}
	
	public long root( long i )
	{
		if( ps[ i ] < 0 ) return i;
		else              return ps[ i ] = root( ps[ i ] );
	}
	
	public bool same( long i, long j )
	{
		return root( i ) == root( j );
	}
	
	public void unite( long i, long j )
	{
		i = root( i );
		j = root( j );
		if( i == j ) return;
		if( rs[ i ] < rs[ j ] )
		{
			ps[ j ] += ps[ i ];
			ps[ i ] = j;
		}
		else
		{
			ps[ i ] += ps[ j ];
			ps[ j ] = i;
			if( rs[ i ] == rs[ j ] ) rs[ i ]++;
		}
	}
}
