Problem:
Score : 300 points

Problem Statement

You are given an undirected connected graph with N vertices and M edges that does not contain self-loops and double edges.

The i-th edge (1 \leq i \leq M) connects Vertex a_i and Vertex b_i.

An edge whose removal disconnects the graph is called a bridge.

Find the number of the edges that are bridges among the M edges.

Notes

A self-loop is an edge i such that a_i=b_i (1 \leq i \leq M).

Double edges are a pair of edges i,j such that a_i=a_j and b_i=b_j (1 \leq i<j \leq M).

An undirected graph is said to be connected when there exists a path between every pair of vertices.

Constraints

2 \leq N \leq 50

N-1 \leq M \leq min(N(N−1)⁄2,50)

1 \leq a_i<b_i \leq N

The given graph does not contain self-loops and double edges.

The given graph is connected.

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1
a_2 b_2
:
a_M b_M

Output

Print the number of the edges that are bridges among the M edges.

Sample Input 1

7 7
1 3
2 7
3 4
4 5
4 6
5 6
6 7

Sample Output 1

4

The figure below shows the given graph:

The edges shown in red are bridges. There are four of them.

Sample Input 2

3 3
1 2
1 3
2 3

Sample Output 2

0

It is possible that there is no bridge.

Sample Input 3

6 5
1 2
2 3
3 4
4 5
5 6

Sample Output 3

5

It is possible that every edge is a bridge.

Solution in Haskell (GHC 7.10.3) (judge verdict: Accepted)

import Control.Monad
import Control.Applicative
import Data.List
import qualified Data.Map as Map
import Data.Array
import qualified Data.ByteString.Char8 as BC
import Data.Maybe
import qualified Data.Set as Set
import qualified Data.Sequence as Sq
import qualified Data.IntMap as IMap
import Data.Sequence (ViewL(..),ViewR(..),(><),(<|),(|>),Seq)

bsreadInt :: BC.ByteString -> Int
bsreadInt = fst . fromJust . BC.readInt

setadj :: [[Int]] -> IMap.IntMap (Set.Set Int) -> IMap.IntMap (Set.Set Int)
setadj [] adj = adj
setadj (x:xs) adj = setadj xs (IMap.insert a add adj) 
                            where a = x!!0
                                  b = x!!1
                                  add = Set.union (Set.singleton b) cs
                                  cs = if IMap.member a adj == True
                                       then (IMap.!) adj a
                                       else Set.empty

--nsetadj :: [[Int]] -> IMap.IntMap (Set.Set Int) -> IMap.IntMap (Set.Set Int)
--nsetadj xs adj = setadj (xs ++ (map reverse xs)) adj

nsetadj :: [[Int]] -> IMap.IntMap (Set.Set Int) -> IMap.IntMap (Set.Set Int)
nsetadj [] adj = adj
nsetadj (x:xs) adj = nsetadj xs (IMap.insert b adda (IMap.insert a addb adj)) 
                                 where a = x!!0
                                       b = x!!1
                                       adda = Set.union (Set.singleton a) csa
                                       addb = Set.union (Set.singleton b) csb
                                       csa = if IMap.member b adj == True
                                             then (IMap.!) adj b
                                             else Set.empty                                       
                                       csb = if IMap.member a adj == True
                                             then (IMap.!) adj a
                                             else Set.empty


main = do
    [n,m] <- map bsreadInt . BC.words <$> BC.getLine --n頂点，m本の辺
    ab <- map ((map bsreadInt . BC.words)) <$> replicateM m BC.getLine -- a-->b :path のリスト
    let q = Sq.singleton [1]
    let chk = Set.singleton 1
    print $ length $ filter (==False) [connectchk q n (nsetadj (ab \\ [ab!!(k-1)]) IMap.empty) chk | k <-[1..m]]
    --print $ length $ filter (==False) [connectchk q n (delete adjs) chk | k <- [1..m]]
    --print $ length $ filter (==False) [connectchk q n (Set.union (Set.fromList (ab \\ [ab!!(k-1)] ) ) (Set.fromList (map reverse (ab \\ [ab!!(k-1)] )) )) chk | k <- [1..m]]

connectchk :: Sq.Seq [Int] -> Int -> IMap.IntMap (Set.Set Int) -> Set.Set Int -> Bool
connectchk q n adjs chk = foldr (&&) True [ (bsearch q n g adjs chk) /= [] | g <- [2..n] ]
         
adjset :: Int -> Int -> IMap.IntMap (Set.Set Int) -> Set.Set Int -> [Int]
adjset x n adjs chk  = Set.toList (Set.difference (f adjs x) chk)
                        where f adj a = if IMap.member a adj == True
                                        then (IMap.!) adj a
                                        else Set.empty

bsearch :: Sq.Seq [Int] -> Int -> Int -> (IMap.IntMap (Set.Set Int) ) -> Set.Set Int -> [Int]
bsearch q n g adjs chk = if Sq.length q == 0
                         then []
                         else if head (sqleft q) == g
                              then reverse $ sqleft q
                              else bsearch q2 n g adjs chk2
                                where qa = sqleft q
                                      q2 = (Sq.drop 1 q) >< (Sq.fromList add)
                                      add = [x : qa | x <- adjset (head qa) n adjs chk]
                                      chk2 = Set.union chk (Set.fromList (adjset (head qa) n adjs chk))
                                      
sqleft :: Seq a -> a
sqleft q = sqleft_(Sq.viewl q)
sqleft_ :: ViewL a -> a
sqleft_ (x :< xs) = x
sqright :: Seq a -> a
sqright q = sqright_(Sq.viewr q)
sqright_ :: ViewR a -> a
sqright_ (xs :> x) = x