{-# OPTIONS_GHC -O #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}

import Control.Monad
import Data.List
import qualified Data.Vector.Storable as V
import qualified Data.Vector.Storable.Mutable as MV

findUF :: MV.IOVector Int -> Int -> IO Int
findUF uf x = do
    p <- MV.unsafeRead uf x
    if p == -1
        then return x
        else do
                f <- findUF uf p
                MV.unsafeWrite uf x f
                return f

u uf [x,y] = do
    px <- findUF uf x
    py <- findUF uf y
    when (px /= py) $ MV.unsafeWrite uf py px

f n _ [] = return []
f n as (e:es) = do
    uf <- MV.replicate (n+1) (-1)
    mapM (u uf) as
    mapM (u uf) es
    rs <- f n (e:as) es
    uff <- V.unsafeFreeze uf
    return $ (V.length $ V.filter (==(-1)) uff) : rs

main=do
    [n,m] <- map read.words<$>getLine
    es <- replicateM m $ map read.words <$> getLine
    ms <- f n [] es
    print $ length $ filter (>2) ms
