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: Runtime Error)

using System;
using System.Collections.Generic;
using System.Linq;
#if !DEBUG
    using System.IO;
#endif

public class CanGo {
    HashSet<int>[] workGraph;
    int goal;

    public CanGo(HashSet<int>[] workGraph, int goal) {
        this.workGraph = workGraph;
        this.goal = goal;
    }

    public bool Connected(int v1, HashSet<int> History) {
        if (v1 == goal) {
            return true;
        }

        var nextNums = workGraph[v1].Where(v => !History.Contains(v)).ToList();
        if (nextNums.Count <= 0) {
            return false;
        }

        var nextHistory = new HashSet<int>(History);
        nextHistory.Add(v1);
        return nextNums.Select(v => Connected(v, nextHistory)).Any();
    }
}

public class Program {
    public static void Main() {
        #region SetAutoFlushIsFalse
#if !DEBUG
        var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
        Console.SetOut(sw);
#endif
        #endregion
        var nm = ReadLib.ReadAsIntArray();
        var n = nm[0];
        var m = nm[1];

        var mArr = ReadLib.ReadNTimesAsIntArray(n);

        var score = CalcScore(n, m, mArr);

        #region Flush
#if !DEBUG
        Console.Out.Flush();
        sw.Close();
#endif
        #endregion
    }

    private static int CalcScore(int n, int m, int[][] mArr) {
        var cnt = 0;

        var graph = CreateGraph(n, mArr);
        foreach (var arr in mArr) {
            HashSet<int>[] workGraph = new HashSet<int>[n];
            graph.CopyTo(workGraph, 0);

            workGraph[arr[0]].Remove(arr[1]);
            workGraph[arr[1]].Remove(arr[0]);
            var cango = new CanGo(workGraph, arr[1]);
            if (cango.Connected(arr[0], new HashSet<int>())) {
                cnt++;
            }
        }
        return cnt;
    }


    private static HashSet<int>[] CreateGraph(int n, int[][] mArr) {
        var graph = new HashSet<int>[n];
        foreach (var item in mArr) {
            graph[item[0]].Add(item[1]);
            graph[item[1]].Add(item[0]);
        }
        return graph;
    }
}

static class ReadLib {
    public static long ReadAsLong() {
        return long.Parse(Console.ReadLine());
    }

    public static int ReadAsInt() {
        return int.Parse(Console.ReadLine());
    }

    public static int[] ReadAsIntArray() {
        return Console.ReadLine().Split(' ').Select(s => int.Parse(s)).ToArray();
    }

    public static long[] ReadAsLongArray() {
        return Console.ReadLine().Split(' ').Select(s => long.Parse(s)).ToArray();
    }

    public static ulong[] ReadAsULongArray() {
        return Console.ReadLine().Split(' ').Select(s => ulong.Parse(s)).ToArray();
    }

    public static string[] ReadAsStringArray() {
        return Console.ReadLine().Split(' ');
    }

    public static int[] ReadNTimesAsInt(int n) {
        return Enumerable.Range(1, n).Select(s => int.Parse(Console.ReadLine())).ToArray();
    }

    public static int[][] ReadNTimesAsIntArray(int n) {
        return Enumerable.Range(1, n).Select(s => ReadAsIntArray()).ToArray();
    }

}

static class MyMath {
    /// <summary>階乗</summary>
    public static long Factorial(int n) {
        if (n == 0) {
            return 1;
        }

        return Permutation(n, 0);
    }

    public static long Permutation(int n, int k) {
        return Enumerable.Range(0, n - k).Select(i => n - i).Aggregate(1, (b, i) => b * i);
    }

    /// <summary>nCr, 組み合わせ</summary>
    public static long Combination(int n, int r) {
        if (r == 0) {
            return 1;
        }
        // 分子
        var moleculeArr = Enumerable
            .Range(0, Math.Min(n - r, r))
            .Select(i => n - i)
            .ToArray();
        var moleculeArrLength = moleculeArr.Length;
        // 分母
        var denominatorArr = Enumerable
            .Range(1, Math.Max(n - r, r))
            .ToArray();

        for (var m = 0; m < moleculeArrLength; m++) {
            while (true) {
                var mVal = moleculeArr[m];
                var gcds = denominatorArr.Select(b => Gcd(mVal, b));
                var maxGcd = gcds.Max();
                var maxI = gcds.ToList().IndexOf(maxGcd);

                if (maxGcd == 1) {
                    break;
                }

                denominatorArr[maxI] /= maxGcd;
                moleculeArr[m] /= maxGcd;
            }
        }

        return FullPower(moleculeArr);
    }

    #region FullPower
    /// <summary>総乗、π</summary>
    public static long FullPower(IEnumerable<long> vs) {
        return vs.Aggregate(1L, (a, b) => a * b);
    }

    public static long FullPower(IEnumerable<int> vs) {
        return vs.Aggregate(1L, (a, b) => a * b);
    }
    #endregion

    /// <summary>最大公約数</summary>
    public static int Gcd(long item1, long item2) {
        var a = Math.Max(item1, item2);
        var b = Math.Min(item1, item2);

        while (true) {
            var mod = a % b;
            if (mod == 0) {
                break;
            }

            a = b;
            b = mod;
        }
        return (int)b;
    }

    /// <summary>約分。最大公約数で割ったものを返す。</summary>
    public static Tuple<long, long> DeviedByGcd(long item1, long item2) {
        var gcd = Gcd(item1, item2);
        return new Tuple<long, long>(item1 / gcd, item2 / gcd);
    }
}

//static class IEnumerableExtention {
//    public static int IndexOfMax<T>(this IEnumerable<T> ts) {
//        var max = ts.Max();
//        return ts.ToList().IndexOf(max);
//    }

//    public static int IndexOfMax<T>(this IEnumerable<T> ts, Func<T, int> func) {
//        var funced = ts.Select(i => func(i));
//        var max = ts.Max(func);
//        return funced.ToList().IndexOf(max);
//    }

//    public static int IndexOfMax<T>(this IEnumerable<T> ts, Func<T, long> func) {
//        var funced = ts.Select(i => func(i));
//        var max = ts.Max(func);
//        return funced.ToList().IndexOf(max);
//    }
//}