import           Control.Monad
import qualified Data.ByteString as B
import           Data.List
import qualified Data.Set        as S
import qualified Data.Vector     as V

readInt :: IO [Int]
readInt = map read . words <$> getLine

readIntlines :: Int -> IO [[Int]]
readIntlines n = map (map read . words) <$> replicateM n getLine

main :: IO ()
main = do
    [n, m] <- readInt
    ab <- readIntlines m
    print $ solve ab

solve :: [[Int]] -> Int
solve xs = V.maximum $ V.map S.size $ foldl' (\acc x -> set x acc) V.empty xs

set :: [Int] -> V.Vector (S.Set Int) -> V.Vector (S.Set Int)
set y gs = let (ts, fs) = V.partition (\c -> or $ map (`S.member` c) y) gs
            in if V.null ts
                  then (S.fromList y) `V.cons` fs
                  else S.unions (S.fromList y : V.toList ts) `V.cons` fs
