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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Library;
using static Library.Input;

namespace AtCoderTemplate {
    class ProgramC {

        static List<int>[] matrix;

        static void Main () {
            int N = NextInt, M = NextInt;
            matrix = Enumerable.Repeat(0, N).Select(_ => new List<int>()).ToArray();
            for (int i = 0; i < M; i++)
            {
                int a = NextInt - 1, b = NextInt - 1;
                matrix[a].Add(b);
                matrix[b].Add(a);
            }

            System.Console.WriteLine(matrix.Select((list, s) => list.Count(g => !Visit(Enumerable.Repeat(false, N).ToArray(), s, s, g))).Sum() / 2);
        }

        static bool Visit(bool[] visited, int now, int start, int goal) {
            if(visited[now]) return visited.All(x => x);

            visited[now] = true;
            if(start == now) return matrix[now].Where(to => to != goal).Any(next => Visit(visited, next, start, goal));
            if(goal == now) return matrix[now].Where(to => to != start).Any(next => Visit(visited, next, start, goal));
            return matrix[now].Any(next => Visit(visited, next, start, goal));
        }
    }

}

namespace Library {
    class Input {
        static IEnumerator<string> enumerator = new string[] { }.AsEnumerable ().GetEnumerator ();

        public static string Line => Console.ReadLine ();

        public static string[] StrArr => Line.Split (' ');

        public static int NextInt => int.Parse (NextWord ());

        public static long NextLong => long.Parse (NextWord ());

        public static List<int> IntList => StrArr.Select (int.Parse).ToList ();

        public static List<long> LongList => StrArr.Select (long.Parse).ToList ();

        public static IEnumerable<long[]> TakeLine (int N) {
            return Enumerable.Repeat (0, N).Select (_ => Console.ReadLine ().Split (' ').Select (long.Parse).ToArray ());
        }

        public static string NextWord () {
            while (!enumerator.MoveNext ()) {
                enumerator = StrArr.AsEnumerable ().GetEnumerator ();
            }
            return enumerator.Current;
        }
    }
}

namespace Library {
    
    class Modular {
        public const int mod = 1000000007;
        public readonly long value;
        public Modular (long value) { this.value = value; }
        public static implicit operator Modular (long a) {
            var m = a % mod;
            return new Modular ((m < 0) ? m + mod : m);
        }
        public static Modular operator + (Modular a, Modular b) {
            return a.value + b.value;
        }
        public static Modular operator - (Modular a, Modular b) {
            return a.value - b.value;
        }
        public static Modular operator * (Modular a, Modular b) {
            return a.value * b.value;
        }
        public static Modular Pow (Modular a, int n) {
            switch (n) {
                case 0:
                    return 1;
                case 1:
                    return a;
                default:
                    var p = Pow (a, n / 2);
                    return p * p * Pow (a, n % 2);
            }
        }
        public static Modular operator / (Modular a, Modular b) {
            return a * Pow (b, mod - 2);
        }
        private static readonly List<int> facs = new List<int> { 1 };
        private static Modular Fac (int n) {
            for (int i = facs.Count; i <= n; ++i) {
                facs.Add ((int) (Math.BigMul (facs.Last (), i) % mod));
            }
            return facs[n];
        }
        public static Modular Ncr (int n, int r) {
            return (n < r) ? 0 :
                (n == r) ? 1 :
                Fac (n) / (Fac (r) * Fac (n - r));
        }
        public static explicit operator int (Modular a) {
            return (int) a.value;
        }
    }

}
namespace Library {
    class MyMath {
        public static long Gcd (long a, long b) {
            return b == 0 ? a : Gcd (b, a % b);
        }

        public static long Sqrt (long n) {
            if (n < 0) return 0;
            long a = 0, tmp = 0, b = 0;
            for (int i = 62; i >= 0; i -= 2) {
                tmp = (b << 1) + 1 <= (n >> i) ? 1 : 0;
                a = a << 1 | tmp;
                n -= (((b << 1) + 1) * tmp) << i;
                b = (b << 1) + tmp + tmp;
            }
            return a;
        }

        public static long Nck (int n, int k) {
            if (k == 0) return 1;
            if (n == 0) return 0;
            return n * Nck (n - 1, k - 1) / k;
        }
    }
}

namespace Library {
        public class PriorityQueue<T> {

        readonly List<T> _heap = new List<T> ();
        readonly Comparison<T> _comparison;

        public PriorityQueue (Comparison<T> comparison) {
            _comparison = comparison;
        }

        public PriorityQueue () : this (Comparer<T>.Default.Compare) { }

        public PriorityQueue (IComparer<T> comparer) : this (comparer.Compare) { }

        public void Enqueue (T item) {
            _heap.Add (item);

            int childID = _heap.Count - 1;
            int parentID = (childID - 1) / 2;

            while (childID > 0 && _comparison (_heap[parentID], _heap[childID]) > 0) {
                Swap (parentID, childID);
                childID = parentID;
                parentID = (parentID - 1) / 2;
            }
        }

        public T Dequeue () {
            var first = _heap.First ();
            _heap[0] = _heap.Last ();
            _heap.RemoveAt (_heap.Count - 1);

            int parentID = 0;
            int childID = parentID * 2 + 2;
            if (childID >= _heap.Count || _comparison (_heap[childID], _heap[childID - 1]) > 0) childID--;

            while (childID < _heap.Count && _comparison (_heap[parentID], _heap[childID]) > 0) {
                Swap (parentID, childID);
                parentID = childID;
                childID = parentID * 2 + 2;
                if (childID >= _heap.Count || _comparison (_heap[childID], _heap[childID - 1]) > 0) childID--;
            }

            return first;
        }

        void Swap (int parent, int child) {
            var tmp = _heap[parent];
            _heap[parent] = _heap[child];
            _heap[child] = tmp;
        }

        public T Peek () { return _heap[0]; }
        public int Count => _heap.Count;
        public bool Any () { return _heap.Any (); }
        public List<T> Data => _heap;
    }
}

namespace Library {
    
    public class UnionFind {
        public int[] Parents { get; set; }
        public UnionFind (int size) {
            Parents = Enumerable.Repeat (-1, size).ToArray ();
        }

        public int Find (int num) {
            if (Parents[num] < 0) return num;

            Parents[num] = Find (Parents[num]);
            return Parents[num];
        }

        public int Size (int num) {
            return -Parents[Find (num)];
        }

        public bool Same (int a, int b) {
            return Find (a) == Find (b);
        }

        public void Unite (int a, int b) {
            int x = Find (a), y = Find (b);

            if (Size (x) > Size (y)) {
                Parents[x] += Parents[y];
                Parents[y] = x;
            } else {
                Parents[y] += Parents[x];
                Parents[x] = y;
            }
        }
    }
}