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: Accepted)

use::std::vec::Vec;
use::std::collections::VecDeque;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn main() {
    let (n, m) = {
      let v: Vec<usize> = read_vec();
      (v[0], v[1])
    };
    let mut brigde: Vec<(usize, usize)> = Vec::new();
    for _ in 0..m {
      let b: (usize, usize) = {
        let v: Vec<usize> = read_vec();
        (v[0] - 1, v[1] - 1)
      };
      brigde.push(b);
    }

    let mut g: Graph = Graph::new(n, &brigde, false);
    let mut result: u64 = 0;

    for &(i, j) in &brigde {
      g.graph[i][j] = -1;
      g.graph[j][i] = -1;
      if n != g.bfs(0, 0, calc) as usize {
        result += 1;
      }
      g.graph[i][j] = 1;
      g.graph[j][i] = 1;
    }

    println!("{}", result);
}

fn calc(result: &mut u64, i: usize, j: usize) {
    *result += 1;
}



#[derive(Debug, Clone)]
struct Graph {
  n: usize,                            // number of nodes
  graph: Vec<Vec<i64>>,              // first: from node, second: to node, third: cost
}

impl Graph {
  // constructor
  fn new(n: usize, v: &Vec<(usize, usize)>, direct: bool) -> Graph {
    let mut g: Vec<Vec<i64>>  = vec![vec![-1; n]; n];
    for &(from, to) in v {
      g[from][to] = 1;
      if !direct {
        g[to][from] = 1;
      }
    }

    Graph { n: n, graph: g, }
  }

  // breadth first search
  fn bfs<R: std::fmt::Debug>(&self, start: usize, init: R, f: fn(&mut R, usize, usize)) -> R {
    let mut result: R = init;                          // result variable
    let mut pre_node: usize;
    let mut visit: Vec<bool> = vec![false; self.n];    // record already visit to node
    let mut q: VecDeque<usize> = VecDeque::new();

    // init
    pre_node = start;
    visit[start] = true;
    q.push_back(start);


    while !q.is_empty() {
      let v: usize = match q.pop_front() {
        None => panic!("unifined"),
        Some(i) => i,
      };

      // caluclate
      f(&mut result, pre_node, v);
      pre_node = v;

      for i in 0..self.n {
        if !visit[i] && self.graph[v][i] > 0 {
          q.push_back(i);
          visit[i] = true;  // already visit node v, so mark
        }
      }
    }
    return result;
  }

  // depth first search
  fn dfs<R>(&self, start: usize, init: R, f: fn(&mut R, usize, usize)) -> R {
    let mut result: R = init;                          // result variable
    let mut pre_node: usize;
    let mut visit: Vec<bool> = vec![false; self.n];    // record already visit to node
    let mut stack: Vec<usize> = Vec::new();

    // init
    pre_node = start;
    visit[start] = true;
    stack.push(start);


    while !stack.is_empty() {
      let v: usize = match stack.pop() {
        None => panic!("unifined"),
        Some(i) => i,
      };

      // caluclate
      f(&mut result, pre_node, v);
      pre_node = v;

      for i in 0..self.n {
        if !visit[i] && self.graph[v][i] > 0 {
          stack.push(i);
          visit[i] = true;  // already visit node v, so mark
        }
      }
    }
    return result;
  }

}