unittest
{
	assert( [ "3 4", "2 1 3", "3 1 2 3", "2 3 2" ].parse.expand.solve == 1 );
	assert( [ "5 5", "4 2 3 4 5", "4 1 3 4 5", "4 1 2 4 5", "4 1 2 3 5", "4 1 2 3 4" ].parse.expand.solve == 0 );
	assert( [ "1 30", "3 5 10 30" ].parse.expand.solve == 3 );
}



import std.algorithm;
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 ass = new long[][]( nm[ 0 ] );
	foreach( ref as; ass )
	{
		input.popFront;
		as = input.front.split.to!( long[] )[ 1 .. $ ];
	}
	return tuple( nm[ 1 ], ass );
}

auto solve( long m, long[][] ass )
{
	foreach( ref as; ass )
	{
		as.sort();
	}
	
	auto ans = 0L;
	auto kis = new long[]( ass.length );
	for( auto i = 0L; i < m; i++ )
	{
		auto c = 0L;
		foreach( ai, as; ass )
		{
			if( kis[ ai ] < as.length && as[ kis[ ai ] ] == i + 1 )
			{
				kis[ ai ]++;
				c++;
			}
		}
		if( c == ass.length ) ans++;
	}
	
	return ans;
}
