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 eps 1e-7
#define PI acos(-1)
#define de(x) cout<<#x<<'='<<x<<" , "
#define dee(x) cout<<#x<<'='<<x<<endl
#define sz(x) (int)x.size()
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<(b);++i)
#define per(i,a,b) for(int i=a;i>(b);--i)
#define mset(a,b) memset(a,b,sizeof(a))
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define pb push_back
#define random(a,b) ((a)+rand()%((b)-(a)+1))
typedef long long LL;
typedef pair<int,char> pii;
typedef vector<int> vi;
const int maxn=100055;
int bridgecnt=0,cutcnt=0;
int clk,dfn[maxn],low[maxn];
vi e[maxn];
void tarjan(int u,int par){
    dfn[u]=low[u]=++clk;
    bool tag=0; int child=0;
    rep(i,0,sz(e[u])){
        int v=e[u][i]; if(v==par) continue;
        if(!dfn[v]){
            child++;
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]) tag=1;
            if(low[v]>dfn[u] ) bridgecnt++;
        }
        else low[u]=min(low[u],dfn[v]);
    }
    if(tag||(par==-1&&child>=1)) cutcnt++;
}
int main(){
    int n,m; cin>>n>>m;
    while(m--){
        int u,v; scanf("%d %d",&u,&v);
        e[u].pb(v);  e[v].pb(u);
    }
    rep(i,1,n+1) if(!dfn[i]) tarjan(i,-1);
    cout<<bridgecnt<<endl;
}