import           Control.Monad
import qualified Control.Monad.State as ST
import           Data.List
import qualified Data.Set            as S

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 >>= (λxs -> return [(x, y) | [x,y] <- xs])
    print $ solve ab
    return ()

solve :: [(Int, Int)] -> Int
solve xs = let groups = groupBy (λx y -> fst x == fst y) . sortOn fst $ xs
               fl = S.fromList
               groupset = map (foldl' (λacc (x, y) -> S.union acc (fl [x, y])) $ fl []) groups
            in maximum $ map S.size (snd $ ST.runState (f groupset) [])
              where
                f []     = return ()
                f (y:ys) = set y >> f ys


set :: S.Set Int -> ST.State [S.Set Int] ()
set y = do
    state <- ST.get
    let (ts, fs) = partition (λc -> or $ S.map (`S.member` c) y) state
    if null ts
       then ST.put $ y : state
       else ST.put $ S.unions (y: ts) : fs