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 Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Main {

    /**
     * 本処理を実行します。
     */
    public static void execute() {
        Scanner sc = new Scanner(System.in);

        int n = nextInt(sc);
        int m = nextInt(sc);

        // NodeList
        List<Node> nodeList = new ArrayList<>(n);

        // Array
        int[][] field = new int[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(field[i], 0);
        }

        for (int i = 0; i < m; i++) {
            int a = nextInt(sc);
            int b = nextInt(sc);

            // Array
            field[a - 1][b - 1]++;
            field[b - 1][a - 1]++;

            // NodeList
            Node aNode = new Node(a);
            Node bNode = new Node(b);

            if (nodeList.contains(aNode)) {
                aNode = nodeList.get(nodeList.indexOf(aNode));
            } else {
                nodeList.add(aNode);
            }

            if (nodeList.contains(bNode)) {
                bNode = nodeList.get(nodeList.indexOf(bNode));
            } else {
                nodeList.add(bNode);
            }

            aNode.linkNodes.add(bNode);
            bNode.linkNodes.add(aNode);
        }

        List<Node> oneLinkNodeList = nodeList.parallelStream().filter(no -> no.linkNodes.size() == 1).collect(Collectors.toList());

        int result = 0;

        for (Node oneLinkNode : oneLinkNodeList) {
            result += oneLinkNode.getNodeCount();
        }

        // Array
        /*int result = 0;
        int[] outNode = new int[n];
        int out = 0;

        for (int i = 0; i < n; i++) {
            if (field[i].length == 1) {
                outNode[out++] = i;

                for (int j = 0; j < n; j++) {

                }
            }
        }

        out (result / 2);*/

        out(result);
    }

    public static class Node {
        int num;
        List<Node> linkNodes = new ArrayList<>();
        List<Node> checkedNode = new ArrayList<>();

        public Node(int num) {
            this.num = num;
        }

        public int getNodeCount() {
            int count = 0;
            List<Node> parents = new ArrayList<>();
            parents.add(this);

            for (Node n : linkNodes) {
                if (!checkedNode.contains(n) ) {

                    checkedNode.add(n);
                    n.checkedNode.add(this);

                    if (n.linkNodes.size() <= 2) {
                        count++;
                    }

                    count += n.getNodeCount(parents);
                }
            }

            return count;
        }

        public int getNodeCount(List<Node> parentNodes) {
            int count = 0;
            parentNodes.add(this);

            for (Node n : linkNodes) {
                if (!parentNodes.contains(n) && !checkedNode.contains(n) ) {

                    checkedNode.add(n);
                    n.checkedNode.add(this);

                    if (n.linkNodes.size() <= 2) {
                        count++;
                    }

                    count += n.getNodeCount(parentNodes);
                }

            }

            return count;
        }

        /* (非 Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + num;
            return result;
        }

        /* (非 Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Node other = (Node) obj;
            if (num != other.num)
                return false;
            return true;
        }

        /* (非 Javadoc)
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return "Node [num=" + num + "]";
        }
    }
    /**
     * 次の標準入力をintで受け取ります。
     * @return 標準入力値(int)
     */
    public static int nextInt(Scanner sc) {
        return sc.nextInt();
    }

    /**
     * 次の標準入力をStringで受け取ります。
     * @return 標準入力値(String)
     */
    public static String nextString(Scanner sc) {
        return sc.next();
    }

    /**
     * 次の標準入力を指定回数分intで受け取ります。
     * @param n 取得回数
     * @return 取得した標準入力値の配列(int)
     */
    public static int[] nextInts(Scanner sc, int n) {
        int[] arr = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = nextInt(sc);
        }

        return arr;
    }

    /**
     * 標準出力にオブジェクトを出力します。
     * @param o 出力対象
     */
    public static void out(Object o) {
        System.out.println(o);
    }

    public static void main(String[] args) {
        execute();
    }


    public static void putCountMap(Map<Integer, Integer> map, int value) {
        if (map.containsKey(value)) {
            map.put(value, map.get(value) + 1);
        } else {
            map.put(value, 1);
        }
    }
}