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++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

#define RESIDUE(u,v) (capacity[u][v] - flow[u][v])
#define RCOST(u,v) (cost[u][v] + h[u] - h[v])
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)   FOR(i,0,n)
#define LL long long

void disp(vector<int> v){
  for(int i=0;i<v.size();i++){
    cout << v[i] << " ";
  }
  cout<<endl;
}

template <typename T>
class undigraph {
public:
  struct edge{
    int from;
    int to;
    T cost;
  };
  
  vector< vector<int> > v;
  vector<edge> edges;

  int n;

  undigraph(int n){
    v.resize(n);
  }

  void add(int from,int to,T cost = 1){
    v[from].push_back(edges.size());
    v[to].push_back(edges.size());
    edges.push_back({from, to, cost});
  }
};

template <typename T>
vector <T> dijkstra(const undigraph<T> &g, int start) {
  vector<T> dist(g.n, numeric_limits<T>::max());
  priority_queue<pair<T, int>, vector<pair<T, int> >, greater<pair<T, int> > > s;
  dist[start] = 0;
  s.emplace(dist[start], start);

  while(!s.empty()){
    /*
    cout<<dist[0] << " " <<dist[1]<< " " <<dist[2]<< " " <<dist[3]<< " " <<dist[4]<< " " <<dist[5]<< " " <<dist[6] <<endl;
    cout<<s.top().first << " "<<s.top().second <<endl;
    */
    int expected = s.top().first;
    int base = s.top().second;
    /*
    if(expected != dist[base]){
      continue;
    }
    */
    s.pop();
    for(int id:g.v[base]){
      auto &e = g.edges[id];
      int to = base ^ e.from ^ e.to;
      if(dist[base] + e.cost < dist[to]){
	dist[to] = dist[base] + e.cost;
	s.emplace(dist[to],to);
      }
    }
  }
  return dist;
}

int i,j;

int main(){
  int n,m,a,b;
  cin>>n>>m;
  undigraph<int> g(n);
  g.n=n;
  REP(i,m){
    cin>>a>>b;
    g.add(a-1,b-1);
  }
  int ret=0;
  REP(i,m){
    g.edges[i].cost = 100000;
    //cout<<"dbg " << g.edges[i].from <<" " <<  g.edges[i].to<<endl;
    vector<int> dist = dijkstra(g,0);
    //cout<<"dbg " << g.edges[i].from <<" " <<  g.edges[i].to<<endl;
    REP(j,n){
      if(dist[j] >= 100000){
	//cout<<"dbg"<<endl;
	ret++;
	break;
      }
    }
    g.edges[i].cost = 1;
  }
  cout<<ret<<endl;
  return 0;
}