{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns          #-}
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MagicHash             #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf            #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ViewPatterns          #-}

import           Control.Applicative
import           Control.Exception
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bool
import qualified Data.ByteString             as B
import qualified Data.ByteString.Builder     as B
import qualified Data.ByteString.Char8       as C
import qualified Data.ByteString.Internal    as B
import qualified Data.ByteString.Unsafe      as B
import           Data.Char
import qualified Data.Foldable               as F
import           Data.Function
import qualified Data.IntMap.Strict          as IM
import qualified Data.IntSet                 as IS
import qualified Data.List                   as L
import qualified Data.Map.Strict             as M
import           Data.Monoid
import           Data.Ord
import           Data.Primitive.MutVar
import qualified Data.Set                    as S
import           Data.Tuple
import qualified Data.Vector                 as V
import qualified Data.Vector.Generic         as G
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed         as U
import qualified Data.Vector.Unboxed.Mutable as UM
import           Debug.Trace
import           Foreign                     hiding (void)
import           GHC.Exts
import qualified System.IO                   as IO
import           Unsafe.Coerce

main :: IO ()
main = do
    [n, m] <- map read.words <$> getLine :: IO [Int]
    edges <- U.map (\(x,y)->(x-1,y-1)) . U.unfoldrN m parseInt2 <$> C.getContents
    case solve n m edges of
        Nothing -> print (-1)
        Just vs -> do
            print $ U.length vs
            putStr.unlines.map show $ U.toList vs

solve :: Int -> Int -> U.Vector Edge -> Maybe (U.Vector Vertex)
solve n m edges = runST $ do
    muf <- newUnionFind n
    flag <- UM.replicate 1 False
    root <- UM.replicate 1 (-(1::Int))
    freq <- UM.replicate n (0::Int)

    U.forM_ edges $ \(u, v) -> do
        found <- UM.unsafeRead flag 0
        unless found $ do
            merged <- uniteM muf u v
            when merged $ do
                UM.unsafeModify freq (+1) u
                UM.unsafeModify freq (+1) v
            unless merged $ do
                UM.unsafeWrite flag 0 True
                UM.unsafeWrite root 0 u
    found <- UM.unsafeRead flag 0
    if (not found)
    then return Nothing
    else do
        u0 <- UM.unsafeRead root 0
        g <- findM muf u0
--        g <- UM.unsafeRead root 0 >>= findM muf
        uf <- runUnionFind muf
        freq' <- U.unsafeFreeze freq
        return $ Just
            $ U.filter (\i -> uf U.! i == g && freq' U.! i == 2)
            $ U.generate n id







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

newtype UnionFind s = UF { internalUF :: UM.MVector s Int }

runUnionFind :: PrimMonad m => UnionFind (PrimState m) -> m (U.Vector Int)
runUnionFind = U.unsafeFreeze . internalUF

newUnionFind :: PrimMonad m => Int -> m (UnionFind (PrimState m))
newUnionFind n = UF <$> UM.replicate n (-1)
{-# INLINE newUnionFind #-}

findM :: PrimMonad m => UnionFind (PrimState m) -> Int -> m Int
findM uf x = go x return
  where
    go !x k = do
        px <- UM.unsafeRead (internalUF uf) x
        if px < 0
        then k x
        else go px $ \ppx -> do
            UM.unsafeWrite (internalUF uf) x ppx
            k ppx
{-# INLINE findM #-}

sizeM :: PrimMonad m => UnionFind (PrimState m) -> Int -> m Int
sizeM uf = fix $ \loop x -> do
    px <- UM.unsafeRead (internalUF uf) x
    if px < 0
    then return $! negate px
    else loop px
{-# INLINE sizeM #-}

uniteM :: PrimMonad m => UnionFind (PrimState m) -> Int -> Int -> m Bool
uniteM uf x y = do
    px <- findM uf x
    py <- findM uf y
    if px == py
    then return False
    else do
        rx <- UM.unsafeRead (internalUF uf) px
        ry <- UM.unsafeRead (internalUF uf) py
        if rx < ry
        then do
            UM.unsafeModify (internalUF uf) (+ry) px
            UM.unsafeWrite  (internalUF uf) py px
        else do
            UM.unsafeModify (internalUF uf) (+rx) py
            UM.unsafeWrite  (internalUF uf) px py
        return True
{-# INLINE uniteM #-}

equivM :: PrimMonad m => UnionFind (PrimState m) -> Int -> Int -> m Bool
equivM uf x y = (==) `liftM` findM uf x `ap` findM uf y
{-# INLINE equivM #-}

-- | O(n)
countGroupM :: PrimMonad m => UnionFind (PrimState m) -> m Int
countGroupM uf = U.length . U.filter (<0) <$> runUnionFind uf
{-# INLINE countGroupM #-}

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

buildDirectedGraph :: Int -> U.Vector Edge -> Graph
buildDirectedGraph n edges = U.create $ do
    offset <- U.unsafeThaw
        . U.scanl' (+) (n + 1)
        . U.unsafeAccumulate (+) (U.replicate n 0)
        . U.map (flip (,) 1)
        . fst
        $ U.unzip edges
    gr <- UM.replicate (UM.length offset + U.length edges) 0
    U.forM_ (U.generate (n + 1) id) $ \i ->
        UM.unsafeRead offset i >>= UM.unsafeWrite gr i
    U.forM_ edges $ \(src, dst) -> do
        pos <- UM.unsafeRead offset src
        UM.unsafeWrite offset src (pos + 1)
        UM.unsafeWrite gr pos dst
    return gr

buildUndirectedGraph :: Int -> U.Vector Edge -> Graph
buildUndirectedGraph n edges
    = buildDirectedGraph n (edges U.++ U.map swap edges)

numVertices :: Graph -> Int
numVertices gr = U.head gr - 1

numEdges :: Graph -> Int
numEdges gr = U.length gr - U.head gr

vertices :: Graph -> U.Vector Vertex
vertices = flip U.generate id . numVertices

adjacent :: Graph -> Int -> U.Vector Vertex
adjacent gr v = U.unsafeSlice offset len gr
  where
    offset = U.unsafeIndex gr v
    len = U.unsafeIndex gr (v + 1) - offset

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

parseInt2 :: Parser (Int, Int)
parseInt2 = runStateT $
    (,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt3 :: Parser (Int, Int, Int)
parseInt3 = runStateT $
    (,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt4 :: Parser (Int, Int, Int, Int)
parseInt4 = runStateT $
    (,,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)