{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns #-}

import           Control.Applicative
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Data.Bool
import qualified Data.ByteString.Char8       as B
import qualified Data.ByteString.Unsafe      as B
import           Data.Char
import           Data.Function
import           Data.Primitive.MutVar
import           Data.Tuple
import qualified Data.Vector                 as V
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed         as U
import qualified Data.Vector.Unboxed.Mutable as UM

main :: IO ()
main = do
    [v, e] <- map read.words <$> getLine
    edges <- U.unfoldrN e (readInt2.B.dropWhile isSpace) <$> B.getContents
    putStr.unlines.map show . solve . fromEdges v $ toUndirectedEdges edges

solve :: Graph -> [Vertex]
solve gr = U.toList $ articulations gr

type Vertex = Int
type Edge = (Vertex, Vertex)
type Graph = V.Vector (U.Vector Vertex)

toUndirectedEdges :: U.Vector Edge -> U.Vector Edge
toUndirectedEdges edges = edges U.++ U.map swap edges

fromEdges :: Int -> U.Vector Edge -> Graph
fromEdges numV edges = V.map U.fromList
    . V.unsafeAccumulate (flip (:)) (V.replicate numV [])
    $ U.convert edges

nothing :: Int
nothing = -1

articulations :: Graph -> U.Vector Vertex
articulations gr | V.length gr <= 1 = U.empty
articulations gr = runST $ do
    low <- UM.replicate numV nothing
    num <- UM.replicate numV nothing
    parent <- UM.replicate numV nothing
    numOfVisited <- newMutVar 0 :: ST s (MutVar s Int)

    let root = 0

    fix `flip` root `flip` nothing $ \dfs !v !p -> do
        !nv <- readMutVar numOfVisited
        UM.unsafeWrite num v nv
        modifyMutVar' numOfVisited (+1)
        UM.unsafeWrite parent v p

        U.forM_ (V.unsafeIndex gr v) $ \child -> do
            isVisited <- (/= nothing) <$> UM.unsafeRead num child
            unless isVisited $
                dfs child v

        UM.unsafeWrite low v nv

        U.forM_ (V.unsafeIndex gr v) $ \child ->
            when (child /= p) $ do
                nc <- UM.unsafeRead num child
                if nc < nv
                then unsafeModify low child (min nc)
                else do
                    lc <- UM.unsafeRead low child
                    unsafeModify low child (min lc)

    ps <- U.unsafeFreeze parent
    ns <- U.unsafeFreeze num
    ls <- U.unsafeFreeze low

    let isRootArticulation = U.length (U.filter (== root) ps) >= 2
    let res = U.map fst
            . flip U.filter (U.indexed ns)
            $ \(v, nv) ->
                U.any ((>=nv) . U.unsafeIndex ls) $ V.unsafeIndex gr v

    return $ bool (U.drop 1) id isRootArticulation res
  where
    !numV = V.length gr

-------------------------------------------------------------------------------

readInt2 :: B.ByteString -> Maybe ((Int,Int), B.ByteString)
readInt2 bs = Just ((x,y),bsy)
  where
    Just (x, bsx) = B.readInt bs
    Just (y, bsy) = B.readInt $ B.unsafeTail bsx

unsafeModify :: (PrimMonad m, GM.MVector mv a)
             => mv (PrimState m) a -> Int -> (a -> a) -> m ()
unsafeModify v i f = GM.unsafeRead v i >>= GM.unsafeWrite v i . f
{-# INLINE unsafeModify #-}