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 Rust (1.15.1) (judge verdict: Wrong Answer)

use std::collections::HashSet;

/// Rustで競技プログラミングの入力をスッキリ記述するマクロ
///
/// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

#[inline]
#[allow(dead_code)]
fn gcd(mut m: u64, mut n: u64) -> u64 {
    if m < n {
        std::mem::swap(&mut m, &mut n);
    }

    loop {
        let k = m % n;
        if k == 0 {
            return n;
        }

        m = n;
        n = k;
    }
}

#[inline]
#[allow(dead_code)]
fn lcm(m: u64, n: u64) -> u64 {
    m / gcd(m, n) * n
}

// 点が辺に接続しているなら true していないなら false
fn incident(v: u64, e: &Vec<u64>) -> bool {
    e.contains(&v)
}

// start_v から start_v までのパスを探索する
fn dfs<'a>(ab_a: &'a Vec<Vec<u64>>, start_v: u64, v: u64, used_e: HashSet<&'a Vec<u64>>) -> Option<HashSet<&'a Vec<u64>>> {
    // println!("v = {}", v);

    for ab in ab_a {
        if !incident(v, ab) {
            // 接合していないなら continue
            continue;
        }

        if used_e.contains(&ab) {
            // 辺が使用済みなら contiue
            continue;
        }

        // 移動先を求める
        let to_v = if v == ab[0] {
            ab[1]
        } else {
            ab[0]
        };

        if to_v == start_v {
            // ループ発見
            // println!("loop v found.");
            return Some(used_e);
        }

        // println!("use edge ({}, {})", ab[0], ab[1]);
        let mut new_used_e = used_e.clone();
        new_used_e.insert(ab);
        let ans = dfs(ab_a, start_v, to_v, new_used_e);

        if ans != None {
            return ans;
        }
    }

    // println!("not loop v found.");
    None
}


fn main() {
    input!{
        n: usize,
        m: usize,
        ab_a: [[u64; 2]; m],
    }

    let mut loop_e = HashSet::new();
    let mut loop_v = HashSet::new();

    for v in 1..(n as u64+1) {
        if loop_v.contains(&v) {
            continue;
        }

        if let Some(new_loop_e) = dfs(&ab_a, v, v, HashSet::new()) {
            for e in new_loop_e {
                loop_e.insert(e);
                loop_v.insert(e[0]);
                loop_v.insert(e[1]);
            }
        }
    }

    println!("{}", m - loop_v.len());
}