def dfs( nod ):
noduri = [x for x in range(0, n) if ( comp[x] == 0 and (drum[nod][x] & drum[x][nod]) ) ]
for i in noduri:
if comp[i] == 0:
comp[i] = nr_comp
dfs( i )
debug = False
fin = open( "ctc.in", "r" )
s = fin.readline()
s = [ int(x) for x in s.split() ]
n, m = s
drum = [ [ 1 if i == j else 0 for j in range ( 0, n ) ] for i in range (0, n ) ]
if debug:
print( drum )
for i in fin:
s = [int(x) - 1 for x in i.split()]
drum[ s[0] ][ s[1] ] = 1;
fin.close()
if debug == True:
print( drum )
for nod in range( 0, n ):
for i in range( 0, n ):
for j in range( 0, n ):
drum[i][j] = drum[i][j] | ( drum[i][nod] & drum[nod][j] )
if debug:
print( drum )
comp = [0] * n
nr_comp = 0
for i in range ( 0, n ):
if comp[i] == 0:
nr_comp += 1
comp[i] = nr_comp
dfs( i )
if debug:
print( nr_comp, comp , sep='\n')
fout = open( "ctc.out", "w" )
fout.write( str( nr_comp ) + '\n' )
for i in range( 0, len(comp) ):
fout.write( str( i + 1 ) + " ")
if i+1 != len(comp) and comp[i+1] != comp[i]:
fout.write( "\n" )
fout.close()