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-----
7 7
1 3
2 7
3 4
4 5
4 6
5 6
6 7

-----Sample Output-----
4

The figure below shows the given graph:
The edges shown in red are bridges. There are four of them.

Difficulty: EASY

Solutions:
class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = list(map(int, input().split()))
edges = []
for i in range(M):
	x = list(map(int, input().split()))
	edges.append(x)
ans = 0
for i in range(M):
	uf = UnionFind(N)
	for j in range(M):
		if j != i:
			uf.union(edges[j][0] - 1, edges[j][1] - 1)
		if j == M - 1 and uf.group_count() != 1:
			ans += 1
print(ans)


import copy
(n, m) = (int(i) for i in input().split())
e = [[int(i) - 1 for i in input().split()] for i in range(m)]
b = arr = [[0 for i in range(n)] for j in range(n)]
for x in e:
	b[x[0]][x[1]] = 1
	b[x[1]][x[0]] = 1

def f(idx):
	used[idx] = 1
	for i in range(n):
		if b_[idx][i] == 1 and used[i] == 0:
			f(i)
count = 0
for x in e:
	b_ = copy.deepcopy(b)
	b_[x[0]][x[1]] = 0
	b_[x[1]][x[0]] = 0
	used = [0] * n
	f(0)
	if used.count(1) != n:
		count += 1
print(count)


from collections import deque
(n, m) = map(int, input().split())
A = [[0] * 2 for i in range(m)]
for i in range(m):
	A[i] = list(map(int, input().split()))
ans = 0
for i in range(m):
	B = [[] for i in range(n)]
	for j in range(m):
		if j == i:
			continue
		B[A[j][0] - 1].append(A[j][1] - 1)
		B[A[j][1] - 1].append(A[j][0] - 1)
	C = [0] * n
	C[0] = 1
	D = deque([0])
	while len(D) > 0:
		x = D[0]
		D.popleft()
		for j in range(len(B[x])):
			if C[B[x][j]] == 0:
				D.append(B[x][j])
				C[B[x][j]] = 1
	if C != [1] * n:
		ans = ans + 1
print(ans)


from collections import deque
(n, m) = map(int, input().split())
X = []
M = [[] for _ in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	X.append([a, b])
	M[a - 1].append(b - 1)
	M[b - 1].append(a - 1)
ans = 0
for i in range(m):
	se = {X[i][0] - 1, X[i][1] - 1}
	q = deque([0])
	visited = [0] * n
	while q:
		s = q.popleft()
		if visited[s] == 1:
			continue
		visited[s] = 1
		for x in M[s]:
			if {s, x} != se:
				q.append(x)
	if sum(visited) != n:
		ans += 1
print(ans)


import sys
sys.setrecursionlimit(10 ** 9)

class UnionFind:

	def __init__(self, n):
		self.n = [-1] * n
		self.r = [0] * n
		self.siz = n

	def find_root(self, x):
		if self.n[x] < 0:
			return x
		else:
			self.n[x] = self.find_root(self.n[x])
			return self.n[x]

	def unite(self, x, y):
		x = self.find_root(x)
		y = self.find_root(y)
		if x == y:
			return
		elif self.r[x] > self.r[y]:
			self.n[x] += self.n[y]
			self.n[y] = x
		else:
			self.n[y] += self.n[x]
			self.n[x] = y
			if self.r[x] == self.r[y]:
				self.r[y] += 1
		self.siz -= 1

	def root_same(self, x, y):
		return self.find_root(x) == self.find_root(y)

	def count(self, x):
		return -self.n[self.find_root(x)]

	def size(self):
		return self.siz
(n, m) = list(map(int, input().split()))
edges = [list(map(int, input().split())) for _ in range(m)]
ans = 0
for i in range(m):
	u = UnionFind(n)
	for j in range(m):
		if j == i:
			continue
		(a, b) = edges[j]
		a -= 1
		b -= 1
		u.unite(a, b)
	if u.size() != 1:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(m)]

def dfs(curr):
	visit[curr] = 1
	for x in graph[curr]:
		if visit[x] == 0:
			dfs(x)
ans = 0
for i in range(m):
	temp = ab[:i] + ab[i + 1:]
	graph = [[] for _ in range(n + 1)]
	for (a, b) in temp:
		graph[a].append(b)
		graph[b].append(a)
	visit = [0] * (n + 1)
	dfs(1)
	if sum(visit[1:]) != n:
		ans += 1
print(ans)


(N, M) = list(map(int, input().split()))
a = []
b = []
for e in range(M):
	(x, y) = list(map(int, input().split()))
	x -= 1
	y -= 1
	a.append(x)
	b.append(y)

def solve(e):
	parent = [i for i in range(N)]

	def find(x, parent):
		y = parent[x]
		while y != parent[y]:
			y = find(y, parent)
		parent[x] = y
		return y

	def unite(a, b, parent):
		x = find(a, parent)
		y = find(b, parent)
		if x != y:
			parent[x] = y
	for i in range(M):
		if i == e:
			continue
		unite(a[i], b[i], parent)
	cnt = [0 for _ in range(N)]
	for i in range(N):
		cnt[find(i, parent)] = 1
	if cnt.count(1) > 1:
		return 1
	else:
		return 0
ans = 0
for i in range(M):
	ans += solve(i)
print(ans)


(N, M) = map(int, input().split())
List = [[int(i) for i in input().split()] for i in range(M)]
S = 0
for i in range(M):
	new_List = list(List)
	del new_List[i]
	islands = [1]
	for i in islands:
		for j in new_List:
			if i in j:
				j = [item for item in j if item not in islands]
				islands.extend(j)
	if len(islands) < N:
		S += 1
print(S)


(n, m) = map(int, input().split())
edges = [[] for i in range(n)]
cnt = 0

def dfs(u):
	global cnt
	global visited
	visited[u] = True
	for v in edges[u]:
		if visited[v] == False:
			dfs(v)
	if all(visited):
		return 0
	else:
		return 1
ab = []
for i in range(m):
	(a, b) = map(int, input().split())
	edges[a - 1].append(b - 1)
	edges[b - 1].append(a - 1)
	ab.append([a, b])
for i in range(m):
	visited = [False] * n
	(a, b) = ab[i]
	edges[a - 1].remove(b - 1)
	edges[b - 1].remove(a - 1)
	cnt += dfs(0)
	edges[a - 1].append(b - 1)
	edges[b - 1].append(a - 1)
print(cnt)


(N, M) = map(int, input().split())
edge = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	edge[a - 1].append(b - 1)
	edge[b - 1].append(a - 1)
cnt = 0
for i in range(N):
	for j in edge[i]:
		E = [[n for n in edge[m] if not ((n, m) == (i, j) or (n, m) == (j, i))] for m in range(N)]
		searched = []
		search = [i]
		while len(search) > 0:
			s = search.pop(0)
			if s in searched:
				continue
			searched.append(s)
			for v in E[s]:
				search.append(v)
		if len(searched) < N:
			cnt += 1
print(int(cnt / 2))


import sys
input = sys.stdin.buffer.readline
(n, m) = map(int, input().split())
es = [list(map(int, input().split())) for _ in range(m)]

def check(s, t):
	q = [0]
	vis = [0] * n
	vis[0] = 1
	while q:
		c = q.pop()
		for x in con[c]:
			if c == s and x == t or (c == t and x == s) or vis[x]:
				continue
			vis[x] = 1
			q.append(x)
	return not all(vis)
con = [[] for _ in range(n)]
for (s, t) in es:
	con[s - 1] += (t - 1,)
	con[t - 1] += (s - 1,)
print(sum((check(s - 1, t - 1) for (s, t) in es)))


class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n + 1)]
		self.rank = [0] * (n + 1)

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if self.rank[x] < self.rank[y]:
			self.parents[x] = y
		else:
			self.parents[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1

	def same_check(self, x, y):
		return self.find(x) == self.find(y)

def __starting_point():
	(N, M) = list(map(int, input().split()))
	bridges = [tuple(map(int, input().split())) for _ in range(M)]
	count = 0
	for i in range(M):
		union_find = UnionFind(N)
		for j in range(M):
			if i == j:
				continue
			(a, b) = bridges[j]
			union_find.union(a, b)
		for j in range(1, N):
			if union_find.find(j) != union_find.find(j + 1):
				count += 1
				break
	print(count)
__starting_point()


(N, M) = map(int, input().split())
G = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	G[a - 1].append([i, b - 1])
	G[b - 1].append([i, a - 1])
cnt = 0
for i in range(M):
	D = [N] * N
	D[0] = 0
	Q = [0]
	while Q:
		s = Q[0]
		Q = Q[1:]
		for (idx, adj) in G[s]:
			if idx != i and D[adj] == N:
				D[adj] = D[s] + 1
				Q.append(adj)
	cnt += 1 if max(D) == N else 0
print(cnt)


import sys
sys.setrecursionlimit(10 ** 9)

def int1(x):
	return int(x) - 1

def II():
	return int(input())

def MI():
	return list(map(int, input().split()))

def MI1():
	return list(map(int1, input().split()))

def LI():
	return list(map(int, input().split()))

def LI1():
	return list(map(int1, input().split()))

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def MS():
	return input().split()

def LS():
	return list(input())

def LLS(rows_number):
	return [LS() for _ in range(rows_number)]

def printlist(lst, k=' '):
	print(k.join(list(map(str, lst))))
INF = float('inf')

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def all_group_count(self):
		return [self.size(r) for r in self.roots()]

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))

def solve():
	(N, M) = MI()
	E = []
	for i in range(M):
		(a, b) = MI1()
		E.append((a, b))
	ans = 0
	for (a, b) in E:
		uf = UnionFind(N)
		for (v1, v2) in E:
			if (v1, v2) == (a, b):
				continue
			uf.union(v1, v2)
		if uf.group_count() > 1:
			ans += 1
	print(ans)

def __starting_point():
	solve()
__starting_point()


import copy
(N, M) = map(int, input().split())
A = [[int(i) - 1 for i in input().split()] for i in range(M)]

def dfs(x):
	if visited[x]:
		return
	visited[x] = True
	for i in range(N):
		if edgemat[x][i]:
			dfs(i)
answer = 0
for i in range(M):
	visited = [False] * N
	Acopy = copy.deepcopy(A)
	del Acopy[i]
	edgemat = [[0] * N for j in range(N)]
	for (m, n) in Acopy:
		edgemat[m][n] = 1
		edgemat[n][m] = 1
	dfs(0)
	if any((visited[y] == False for y in range(N))):
		answer += 1
print(answer)


class UnionFind:

	def __init__(self, N):
		self.par = [-1] * N

	def unite(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return False
		if self.par[x] > self.par[y]:
			(x, y) = (y, x)
		self.par[x] += self.par[y]
		self.par[y] = x
		return True

	def root(self, x):
		if self.par[x] < 0:
			return x
		self.par[x] = self.root(self.par[x])
		return self.par[x]

	def size(self, x):
		return -self.par[self.root(x)]
(N, M) = map(int, input().split())
Edge = []
for _ in range(M):
	(u, v) = map(int, input().split())
	Edge.append((u - 1, v - 1))
ans = 0
for e in Edge:
	uf = UnionFind(N)
	for _e in Edge:
		if e == _e:
			continue
		uf.unite(_e[0], _e[1])
	if uf.size(0) != N:
		ans += 1
print(ans)


(n, m) = list(map(int, input().split()))
adj = [[0] * (n + 1) for _ in range(n + 1)]
edges = [tuple(map(int, input().split())) for _ in range(m)]
cnt = 0
for e in edges:
	(x, y) = e
	adj[x][y] = 1
	adj[y][x] = 1

def dfs(s):
	seen[s] = 1
	for nx in range(1, n + 1):
		if adj[s][nx]:
			if seen[nx]:
				continue
			dfs(nx)
for bridge in edges:
	(bx, by) = bridge
	adj[bx][by] = 0
	adj[by][bx] = 0
	seen = [0] * (n + 1)
	dfs(1)
	is_ok = 1
	if any((seen[i] == 0 for i in range(1, n + 1))):
		is_ok = 0
	if not is_ok:
		cnt += 1
	adj[bx][by] = 1
	adj[by][bx] = 1
print(cnt)


(n, m) = list(map(int, input().split()))
a = []
for i in range(m):
	a.append(list(map(int, input().split())))
b = [[0 for i in range(n)] for j in range(n)]
for i in a:
	b[i[1] - 1][i[0] - 1] = 1
	b[i[0] - 1][i[1] - 1] = 1
c = [sum(b[i]) for i in range(n)]
ans = 0
while 1 in c:
	d = c.index(1)
	e = b[d].index(1)
	b[e][d] = 0
	b[d][e] = 0
	c = [sum(b[i]) for i in range(n)]
	ans += 1
print(ans)


(n, m) = map(int, input().split())
s = [list(map(int, input().split())) for i in range(m)]
ans = 0
for i in s:
	l = list(range(n))
	for j in s:
		if i != j:
			l = [l[j[0] - 1] if l[k] == l[j[1] - 1] else l[k] for k in range(n)]
	if len(set(l)) != 1:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
es = [tuple(map(lambda x: int(x) - 1, input().split())) for i in range(M)]
gr = [[] for i in range(N)]
for (i, (a, b)) in enumerate(es):
	gr[a].append((b, i))
	gr[b].append((a, i))
ans = 0
for i in range(M):
	visited = [0] * N
	stack = [0]
	while stack:
		v = stack.pop()
		visited[v] = 1
		for (to, e) in gr[v]:
			if visited[to]:
				continue
			if i == e:
				continue
			stack.append(to)
	if sum(visited) < N:
		ans += 1
print(ans)


def resolve():
	(n, m) = map(int, input().split())
	edges = [list(map(lambda x: int(x) - 1, input().split())) for _ in range(m)]
	ans = 0
	for x in edges:
		C = list(range(n))
		for y in edges:
			if y == x:
				continue
			C = [C[y[0]] if C[i] == C[y[1]] else C[i] for i in range(n)]
		if len(set(C)) != 1:
			ans += 1
	print(ans)
resolve()


import copy
(N, M) = map(int, input().split())
path_matrix = [[0 for i in range(N)] for j in range(N)]
L = [[] for i in range(M)]
for i in range(M):
	(a, b) = map(int, input().split())
	path_matrix[a - 1][b - 1] = 1
	path_matrix[b - 1][a - 1] = 1
	L[i].append(a)
	L[i].append(b)
color_white = ['W' for i in range(N)]
color_black = ['B' for i in range(N)]
visited = copy.deepcopy(color_white)

def path(x, y):
	path_matrix[x - 1][y - 1] = 0
	path_matrix[y - 1][x - 1] = 0
	return DFS(x, path_matrix)

def DFS(x, tim):
	visited[x - 1] = 'B'
	if visited == color_black:
		return True
	total_ans = 0
	for i in range(N):
		if tim[x - 1][i] == 1 and visited[i] == 'W':
			total_ans = int(DFS(i + 1, tim))
	return total_ans
ans = 0
for i in range(M):
	visited = copy.deepcopy(color_white)
	if path(L[i][0], L[i][1]) == 0:
		ans += 1
	path_matrix[L[i][0] - 1][L[i][1] - 1] = 1
	path_matrix[L[i][1] - 1][L[i][0] - 1] = 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x
(N, M) = map(int, input().split())
ans = 0
A = []
B = []
for _ in range(M):
	(a, b) = map(int, input().split())
	A.append(a)
	B.append(b)
for i in range(M):
	uf = UnionFind(N + 1)
	for j in range(M):
		if i == j:
			continue
		uf.union(A[j], B[j])
	else:
		if abs(min(uf.parents[1:])) != N:
			ans += 1
print(ans)


class DisjointSet:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def size(self, x):
		return -self.parents[self.find(x)]
(N, M, *ab) = list(map(int, open(0).read().split()))
edges = [(a - 1, b - 1) for (a, b) in zip(*[iter(ab)] * 2)]
ans = 0
for i in range(M):
	ds = DisjointSet(N)
	for j in range(M):
		if i == j:
			continue
		ds.union(*edges[j])
	if len([-p for p in ds.parents if p < 0]) > 1:
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x
(n, m) = map(int, input().split())
a = [list(map(int, input().split())) for i in range(m)]
ans = 0
for i in range(m):
	uf = UnionFind(n + 1)
	cnt = 0
	for j in range(m):
		if i == j:
			continue
		else:
			uf.union(a[j][0], a[j][1])
	for k in uf.parents:
		if k < 0:
			cnt += 1
	if cnt != 2:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
edges = [list(map(int, input().split())) for _ in range(M)]

def dfs(A, n):
	for a in A[n]:
		if visited[a - 1] == -1:
			visited[a - 1] = 1
			dfs(A, a - 1)
	if -1 in visited:
		return True
	else:
		return False
ans = 0
for i in range(M):
	A = [[] for _ in range(N)]
	edges_new = edges[:i] + edges[i + 1:]
	for (a, b) in edges_new:
		A[a - 1].append(b)
		A[b - 1].append(a)
	visited = [-1] * N
	visited[0] = 1
	if dfs(A, 0):
		ans += 1
print(ans)


def FindParent(X):
	if Parent[X] == X:
		return X
	else:
		Parent[X] = FindParent(Parent[X])
		return Parent[X]

def UniteParent(X, Y):
	X = FindParent(X)
	Y = FindParent(Y)
	if X == Y:
		return 0
	if Rank[X] < Rank[Y]:
		Parent[X] = Y
	else:
		Parent[Y] = X
		if Rank[X] == Rank[Y]:
			Rank[X] += 1
import copy
(N, M) = (int(T) for T in input().split())
List = [[] for TM in range(0, M)]
for TM in range(0, M):
	List[TM] = [int(T) for T in input().split()]
Count = 0
for TM in range(0, M):
	ListCopy = copy.deepcopy(List)
	del ListCopy[TM]
	Parent = [I for I in range(N + 1)]
	Rank = [0] * (N + 1)
	for TTM in range(0, M - 1):
		UniteParent(ListCopy[TTM][0], ListCopy[TTM][1])
	for TN in range(1, N + 1):
		FindParent(TN)
	if len(set(Parent[1:])) > 1:
		Count += 1
print(Count)


(N, M) = map(int, input().split())
AB = [tuple(map(int, input().split())) for i in range(M)]

class UnionFind:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self._size = [1] * N
		self.count = 0

	def root(self, a):
		if self.parent[a] == a:
			return a
		else:
			self.parent[a] = self.root(self.parent[a])
			return self.parent[a]

	def is_same(self, a, b):
		return self.root(a) == self.root(b)

	def unite(self, a, b):
		ra = self.root(a)
		rb = self.root(b)
		if ra == rb:
			return
		if self._size[ra] < self._size[rb]:
			(ra, rb) = (rb, ra)
		self._size[ra] += self._size[rb]
		self.parent[rb] = ra
		self.count += 1

	def size(self, a):
		return self._size[self.root(a)]
ans = 0
for i in range(M):
	uf = UnionFind(N)
	for (j, (a, b)) in enumerate(AB):
		if i == j:
			continue
		(a, b) = (a - 1, b - 1)
		if uf.is_same(a, b):
			continue
		uf.unite(a, b)
	if uf.size(0) != N:
		ans += 1
print(ans)


3
from collections import defaultdict

class UnionFind(object):

	def __init__(self, N):
		self.parent = [x for x in range(N)]

	def root(self, x):
		if self.parent[x] == x:
			return x
		return self.root(self.parent[x])

	def unite(self, x, y):
		root_x = self.root(x)
		root_y = self.root(y)
		if root_x != root_y:
			self.parent[root_x] = root_y

	def same(self, x, y):
		root_x = self.root(x)
		root_y = self.root(y)
		return root_x == root_y

	def num_group(self):
		return sum((1 for i in range(len(self.parent)) if self.parent[i] == i))
(N, M) = (int(x) for x in input().split())
B = [[int(x) - 1 for x in input().split()] for _ in range(M)]

def isBridge(nth):
	union_find = UnionFind(N)
	for i in range(M):
		if i == nth:
			continue
		union_find.unite(B[i][0], B[i][1])
	if union_find.num_group() != 1:
		return 1
ret = 0
for i in range(M):
	if isBridge(i):
		ret += 1
print(ret)


(N, M) = map(int, input().split())
pair = [list(map(lambda x: int(x) - 1, input().split())) for _ in range(M)]
graph = [[0] * N for _ in range(N)]
for p in pair:
	graph[p[0]][p[1]] = graph[p[1]][p[0]] = 1

def DFS(v):
	if visited[v]:
		return
	visited[v] = True
	for j in [j for (j, v2) in enumerate(graph[v]) if v2 == 1]:
		DFS(j)
res = 0
for i in range(M):
	visited = [False for _ in range(N)]
	(x, y) = pair[i]
	graph[x][y] = graph[y][x] = 0
	DFS(0 if i > 0 else 1)
	if not all(visited):
		res += 1
	graph[x][y] = graph[y][x] = 1
print(res)


(n, m) = map(int, input().split())
c = [[0] * n for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	c[a - 1][b - 1] = 1
	c[b - 1][a - 1] = 1
ans = 0
for k in range(n):
	for i in range(n):
		if sum(c[i]) == 1:
			ans += 1
			for j in range(n):
				if c[i][j] == 1:
					c[i][j] = 0
					c[j][i] = 0
print(ans)


from collections import deque

def BFS(N, M, List):
	Edge = [[] for TN in range(N + 1)]
	for TM in range(0, M):
		Edge[List[TM][0]].append(List[TM][1])
		Edge[List[TM][1]].append(List[TM][0])
	Distance = [-1] * (N + 1)
	Distance[0] = 0
	Distance[1] = 0
	From = [0] * (N + 1)
	From[1] = 1
	Deque = deque()
	Deque.append(1)
	while Deque:
		Now = Deque.popleft()
		for Con in Edge[Now]:
			if Distance[Con] == -1:
				Distance[Con] = Distance[Now] + 1
				Deque.append(Con)
				From[Con] = Now
	return (Distance[1:], From[1:])
import copy
(N, M) = (int(T) for T in input().split())
List = [[] for TM in range(0, M)]
for TM in range(0, M):
	List[TM] = [int(T) for T in input().split()]
Count = 0
for TM in range(0, M):
	ListCopy = copy.deepcopy(List)
	del ListCopy[TM]
	(Distance, From) = BFS(N, M - 1, ListCopy)
	if -1 in Distance:
		Count += 1
print(Count)


class UnionFindWithSize:

	def __init__(self, size):
		self.parent = [i for i in range(size)]
		self.size = [1] * size

	def find(self, x):
		if self.parent[x] == x:
			return x
		self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def unite(self, x, y):
		(x, y) = (self.find(x), self.find(y))
		if x == y:
			return
		if self.size[x] < self.size[y]:
			self.size[y] += self.size[x]
			self.parent[x] = y
		else:
			self.size[x] += self.size[y]
			self.parent[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def sizeofset(self, x):
		return self.size[self.find(x)]

def __starting_point():
	(N, M) = map(int, input().split())
	edges = [tuple(map(lambda x: int(x) - 1, input().split())) for _ in range(M)]
	ans = 0
	for i in range(M):
		uf = UnionFindWithSize(N)
		for j in range(M):
			if j != i:
				(a, b) = edges[j]
				uf.unite(a, b)
		if uf.sizeofset(0) != N:
			ans += 1
	print(ans)
__starting_point()


from collections import defaultdict
(N, M) = list(map(int, input().split()))
G = defaultdict(list)
AB = []
for _ in range(M):
	(a, b) = list(map(int, input().split()))
	(a, b) = (a, b)
	G[a].append(b)
	G[b].append(a)
	AB.append((a, b))

def f(a, b):
	S = set([])
	Q = [1]
	while True:
		QQ = []
		for q in Q:
			S.add(q)
			for j in G[q]:
				if q == a and j == b:
					continue
				if q == b and j == a:
					continue
				if j not in S:
					QQ.append(j)
		if len(QQ) == 0:
			break
		Q = QQ
	return 1 if len(S) != N else 0
cnt = 0
for (a, b) in AB:
	cnt += f(a, b)
print(cnt)


(N, M) = list(map(int, input().split()))
A = [[0 for j in range(N + 1)] for i in range(N + 1)]
for i in range(M):
	(a, b) = list(map(int, input().split()))
	A[a][b] = 1
	A[b][a] = 1
br = 0
t = True
while t:
	t = False
	for i in range(N + 1):
		c = 0
		k = -1
		for j in range(len(A[i])):
			if A[i][j] == 1:
				c += 1
				k = j
		if c == 1:
			t = True
			A[i][k] = 0
			A[k][i] = 0
			br += 1
print(br)


import collections
(v, e) = map(int, input().split())
g = [list(map(int, input().split())) for _ in range(e)]
ans = 0
for i in range(e):
	tmp = g[:i] + g[i + 1:]
	ga = [[] for _ in range(v + 1)]
	for j in range(e - 1):
		(s, t) = (tmp[j][0], tmp[j][1])
		ga[s].append(t)
		ga[t].append(s)
	visited = [0] * (v + 1)
	queue = collections.deque([1])
	visited[1] = 1
	while 1:
		if len(queue) == 0:
			break
		tv = queue.popleft()
		for i in ga[tv]:
			if visited[i] == 0:
				queue.append(i)
				visited[i] = 1
	if visited.count(1) != v:
		ans += 1
print(ans)


def dfs(current):
	for maps in Graph[current]:
		if maps in already:
			continue
		else:
			already.append(maps)
			dfs(maps)
(n, m) = map(int, input().split())
ans = 0
Edges = []
for _ in range(m):
	Edges.append([int(j) - 1 for j in input().split()])
for i in range(m):
	egdes = Edges[0:i] + Edges[i + 1:]
	Graph = [[] for _ in range(n)]
	for edge in egdes:
		Graph[edge[0]].append(edge[1])
		Graph[edge[1]].append(edge[0])
	already = []
	dfs(0)
	if len(already) != n:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
E = [[] for _ in range(N)]
lst = []
for i in range(M):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	E[x].append(y)
	E[y].append(x)
	lst.append((x, y))
cnt = 0
for (x, y) in lst:
	stack = [0]
	seen = [0] * N
	seen[0] = 1
	while stack:
		u = stack.pop()
		for v in E[u]:
			if u == x and v == y or (u == y and v == x):
				pass
			elif seen[v] == 0:
				seen[v] = 1
				stack.append(v)
	if sum(seen) == N:
		pass
	else:
		cnt += 1
print(cnt)


(N, M) = map(int, input().split())
s = [[] for i in range(N)]
m = []
for i in range(M):
	(a, b) = map(int, input().split())
	s[a - 1].append(b)
	s[b - 1].append(a)
	m.append([a, b])
ans = 0
from collections import deque
import copy
d = deque()
for i in range(M):
	n = [0] * N
	a = m[i][0]
	b = m[i][1]
	c = s[a - 1].copy()
	c.remove(b)
	d.append(c)
	n[a - 1] = 1
	while len(d) > 0:
		e = d.popleft()
		for j in e:
			if n[j - 1] == 0:
				n[j - 1] = 1
				d.append(s[j - 1])
	if 0 in n:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
P = [list(map(int, input().split())) for k in range(M)]
ans = 0
for i in range(M):
	T = P[:i] + P[i + 1:]
	G = [[] for k in range(N)]
	V = [0 for k in range(N)]
	for e in T:
		G[e[0] - 1].append(e[1] - 1)
		G[e[1] - 1].append(e[0] - 1)

	def dfs(visited, graph, ima):
		for e in graph[ima]:
			if visited[e] == 0:
				visited[e] = 1
				dfs(visited, graph, e)
	dfs(V, G, 0)
	if sum(V) != N:
		ans += 1
print(ans)


from collections import defaultdict as dd
(n, m) = map(int, input().split())
dic = dd(list)
l = []
cnt = 0
for _ in range(m):
	(a, b) = map(int, input().split())
	l.append((a, b))
	dic[a].append(b)
	dic[b].append(a)

def con(x):
	visit.add(x)
	for i in dic[x]:
		if i in visit:
			continue
		con(i)
	return visit == set(range(1, n + 1))
for (x, y) in l:
	dic[x].remove(y)
	dic[y].remove(x)
	visit = set()
	if not con(x):
		cnt += 1
	dic[x].append(y)
	dic[y].append(x)
print(cnt)


class UnionFind:

	def __init__(self, n):
		self.parents = list(range(n))
		self.size = [1] * n

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.size[x] < self.size[y]:
			self.size[y] += self.size[x]
			self.parents[x] = y
		else:
			self.size[x] += self.size[y]
			self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(n, m) = list(map(int, input().split()))
num = [list(map(int, input().split())) for _ in range(m)]
ans = 0
for i in range(m):
	uf = UnionFind(n)
	for j in range(m):
		if i != j:
			uf.union(num[j][0] - 1, num[j][1] - 1)
	if uf.size[uf.find(0)] != n:
		ans += 1
print(ans)


from sys import stdin
nii = lambda : map(int, stdin.readline().split())
lnii = lambda : list(map(int, stdin.readline().split()))
from collections import deque
from copy import deepcopy
(n, m) = nii()
l = [lnii() for i in range(m)]

def BFS(t_l):
	tree = [[] for i in range(n)]
	for (a, b) in t_l:
		a -= 1
		b -= 1
		tree[a].append(b)
		tree[b].append(a)
	dist = [-1 for i in range(n)]
	dist[0] = 0
	que = deque()
	que.append(0)
	while que:
		x = que.popleft()
		for i in tree[x]:
			if dist[i] == -1:
				que.append(i)
				dist[i] = dist[x] + 1
	return dist
ans = 0
for i in range(m):
	t_l = deepcopy(l)
	del t_l[i]
	dist = BFS(t_l)
	if -1 in dist:
		ans += 1
print(ans)


def findunit(edges, N):
	roots = [i for i in range(N)]
	for edge in edges:
		if roots[edge[0]] == roots[edge[1]]:
			continue
		prv_root = roots[edge[1]]
		for (idx, root) in enumerate(roots):
			if root == prv_root:
				roots[idx] = roots[edge[0]]
	return roots
(N, M) = map(int, input().split())
edges = [[int(a) - 1 for a in input().split()] for _ in range(M)]
ans = 0
for i in range(M):
	if len(set(findunit(edges[:i] + edges[i + 1:], N))) != 1:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
ab = list((list(map(int, input().split())) for _ in range(M)))
graph = list(([0] * N for _ in range(N)))
ans = 0
for (a, b) in ab:
	graph[a - 1][b - 1] = 1
	graph[b - 1][a - 1] = 1

def dfs(s):
	visited[s] = 1
	for i in range(N):
		if graph[s][i] == 0 or visited[i] == 1:
			continue
		dfs(i)
for (a, b) in ab:
	graph[a - 1][b - 1] = 0
	graph[b - 1][a - 1] = 0
	visited = [0] * N
	dfs(0)
	graph[a - 1][b - 1] = 1
	graph[b - 1][a - 1] = 1
	if sum(visited) < N:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
ab = [list(map(int, input().split())) for i in range(m)]
ans = 0
for i in range(m):
	graph = [list() for i in range(n + 1)]
	visited = [True] + [False] * n
	for (k, (a, b)) in enumerate(ab):
		if k == i:
			continue
		graph[a].append(b)
		graph[b].append(a)
	NEXT = [1]
	while len(NEXT):
		now = NEXT.pop()
		for j in graph[now]:
			if not visited[j]:
				visited[j] = True
				NEXT.append(j)
	if not all([j for j in visited]):
		ans += 1
print(ans)


(N, M) = map(int, input().split())
A = [[0 for j in range(N)] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	A[a - 1][b - 1] = 1
	A[b - 1][a - 1] = 1
flag = True
ans = 0
while flag:
	flag = False
	for i in range(N):
		if A[i].count(1) == 1:
			flag = True
			ans += 1
			j = A[i].index(1)
			A[i][j] = 0
			A[j][i] = 0
print(ans)


(n, m) = map(int, input().split())
a = [0] * m
b = [0] * m
for i in range(m):
	(a[i], b[i]) = map(int, input().split())

def check(l):
	r = [False] * (n + 1)
	r[0] = True
	r[1] = True
	c = 1
	while c > 0:
		c = 0
		for i in l:
			if r[a[i]] ^ r[b[i]]:
				r[a[i]] = True
				r[b[i]] = True
				c += 1
	if all(r):
		return True
	else:
		return False
c = 0
for i in range(m):
	if not check(list(range(i)) + list(range(i + 1, m))):
		c += 1
print(c)


from typing import List, Tuple

def main():
	(n, m) = list(map(int, input().split()))
	g = []
	for _ in range(m):
		(a, b) = list(map(int, input().split()))
		g.append((a, b))
	print(bb(n, m, g))

def bb(n: int, m: int, g: List[Tuple[int, int]]):
	ret = 0
	for i in range(m):
		v = set()
		w = [1]
		while w:
			now = w.pop()
			v.add(now)
			for (j, node) in enumerate(g):
				if j == i:
					continue
				if node[0] == now and node[1] not in v:
					w.append(node[1])
				elif node[1] == now and node[0] not in v:
					w.append(node[0])
		if len(v) != n:
			ret += 1
	return ret

def __starting_point():
	main()
__starting_point()


(N, M) = map(int, input().split())
(A, B, Ans) = ([[] for _ in range(N)], [], 0)

def s(v, a, b):
	visited[v] = True
	for n in A[v]:
		if not visited[n] and set([v, n]) != set([a, b]):
			s(n, a, b)
for i in range(M):
	(a, b) = map(int, input().split())
	A[a - 1].append(b - 1)
	A[b - 1].append(a - 1)
	B.append((a - 1, b - 1))
for i in range(M):
	visited = [True] + [False] * (N - 1)
	(a, b) = B[i]
	s(0, a, b)
	if visited != [True] * N:
		Ans += 1
print(Ans)


(N, M) = map(int, input().split())

def dfs(v, a, b):
	visited[v] = True
	for n in E1[v]:
		if not visited[n] and set([v, n]) != set([a, b]):
			dfs(n, a, b)
E1 = [[] for _ in range(N)]
E2 = []
Ans = 0
for i in range(M):
	(a, b) = map(int, input().split())
	E1[a - 1].append(b - 1)
	E1[b - 1].append(a - 1)
	E2.append((a - 1, b - 1))
for i in range(M):
	visited = [True] + [False] * (N - 1)
	(a, b) = E2[i]
	dfs(0, a, b)
	if visited != [True] * N:
		Ans += 1
print(Ans)


from itertools import combinations

class unionfind:

	def __init__(self, n):
		self.par = [i for i in range(n)]
		self.rank = [1] * n

	def root(self, a):
		if self.par[a] == a:
			return a
		parent = self.root(self.par[a])
		self.par[a] = parent
		return parent

	def unite(self, a, b):
		(ra, rb) = (self.root(a), self.root(b))
		if ra == rb:
			return
		if self.rank[ra] > self.rank[rb]:
			(ra, rb) = (rb, ra)
		self.par[rb] = ra
		self.rank[ra] += 1

	def same(self, a, b):
		return self.root(a) == self.root(b)

def main():
	(n, m) = map(int, input().split())
	edges = [tuple(map(int, input().split())) for _ in range(m)]
	sm = 0
	for e_remove in edges:
		uf = unionfind(n)
		for e in edges:
			if e == e_remove:
				continue
			uf.unite(e[0] - 1, e[1] - 1)
		for a in combinations(range(n), 2):
			if not uf.same(a[0], a[1]):
				break
		else:
			continue
		sm += 1
	print(sm)
main()


from collections import deque
from sys import stdin
input = stdin.readline

class Unionfind:

	def __init__(self, n):
		self.n = n
		self.parent = [-1] * n

	def find(self, x):
		if self.parent[x] < 0:
			return x
		else:
			self.parent[x] = self.find(self.parent[x])
			return self.parent[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parent[x] < self.parent[y]:
			(x, y) = (y, x)
		self.parent[x] += self.parent[y]
		self.parent[y] = x
(N, M) = map(int, input().split())
A = [-1] * M
B = [-1] * M
for i in range(M):
	(a, b) = map(lambda x: int(x) - 1, input().split())
	A[i] = a
	B[i] = b
ans = 0
for exclude_idx in range(M):
	uf = Unionfind(N)
	for i in range(M):
		if i == exclude_idx:
			continue
		uf.union(A[i], B[i])
	cnt = 0
	for parent in uf.parent:
		if parent < 0:
			cnt += 1
	if cnt >= 2:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
l = [[] for i in range(N)]
e = [[int(i) for i in input().split()] for i in range(M)]
e0 = e
c = 0

def DFS(v):
	seen.append(v)
	for v2 in l[v]:
		if not v2 in seen:
			DFS(v2)
	return seen
for i in range(M):
	seen = []
	l = [[] for i in range(N)]
	for j in range(M):
		if j != i:
			l[e[j][0] - 1].append(e[j][1] - 1)
			l[e[j][1] - 1].append(e[j][0] - 1)
	S = DFS(0)
	if len(S) != N:
		c += 1
print(c)


(n, m) = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(m)]

def dfs(x):
	if visit[x] == True:
		return
	visit[x] = True
	for i in range(n):
		if graph[x][i] == True:
			dfs(i)
ans = 0
for i in range(m):
	graph = [[False] * n for _ in range(n)]
	for j in range(m):
		if j != i:
			(a, b) = AB[j]
			graph[a - 1][b - 1] = True
			graph[b - 1][a - 1] = True
	visit = [False] * n
	dfs(0)
	if sum(visit) != n:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(M)]

class Union_Find:

	def __init__(self, n):
		self.par = [-1] * n
		self.siz = [1] * n

	def root(self, x):
		if self.par[x] == -1:
			return x
		else:
			return self.root(self.par[x])

	def issame(self, x, y):
		return self.root(x) == self.root(y)

	def unite(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return False
		if self.siz[x] < self.siz[y]:
			tmp = x
			x = y
			y = tmp
		self.par[y] = x
		self.siz[x] += self.siz[y]
		return True

	def size(self, x):
		return self.siz[x]
ans = 0
for m in range(M):
	uf = Union_Find(N)
	for i in range(M):
		if i == m:
			continue
		(a, b) = AB[i]
		a -= 1
		b -= 1
		uf.unite(a, b)
	ans += len(set([uf.root(x) for x in range(N)])) != 1
print(ans)


import sys
sys.setrecursionlimit(10 ** 7)

def input():
	return sys.stdin.readline().strip()

def INT():
	return int(input())

def MAP():
	return map(int, input().split())

def LIST():
	return list(MAP())

def NIJIGEN(H):
	return [list(input()) for i in range(H)]

def dfs(j):
	if j not in finish:
		finish.add(j)
		for k in L[j]:
			dfs(k)
(N, M) = MAP()
s = list()
L = [[] for _ in range(N)]
for i in range(M):
	(a, b) = MAP()
	a -= 1
	b -= 1
	L[a].append(b)
	L[b].append(a)
	s.append([a, b])
ans = 0
for i in range(M):
	(a, b) = s[i]
	L[a].remove(b)
	L[b].remove(a)
	finish = set()
	dfs(a)
	if len(finish) != N:
		ans += 1
	L[a].append(b)
	L[b].append(a)
print(ans)


(n, m) = map(int, input().split())
e = []
for _ in range(m):
	(a, b) = map(int, input().split())
	e += [(a - 1, b - 1)]

def dfs(con, v, mat):
	if con[v] == 1:
		return
	con[v] = 1
	for x in mat[v]:
		dfs(con, x, mat)

def is_connected(n, mat):
	con = [0] * n
	dfs(con, 0, mat)
	return sum(con) == n
ans = 0
for i in range(m):
	mat = [[] for _ in range(n)]
	for j in range(m):
		if j == i:
			continue
		mat[e[j][0]] += [e[j][1]]
		mat[e[j][1]] += [e[j][0]]
	if not is_connected(n, mat):
		ans += 1
print(ans)


def par(a):
	if P[a] == a:
		return a
	t = par(P[a])
	P[a] = t
	return t

def unite(a, b):
	P[par(b)] = par(a)
(N, M) = map(int, input().split())
X = [[int(a) - 1 for a in input().split()] for _ in range(M)]
ans = 0
for i in range(M):
	P = [i for i in range(N)]
	for j in range(M):
		if i != j:
			unite(X[j][0], X[j][1])
	if sum([1 if par(i) == i else 0 for i in range(N)]) > 1:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
e = []
for i in range(m):
	e.append(list(map(int, input().split())))
ans = 0
for i in range(m):
	g = [[] for _ in range(n)]
	for j in range(m):
		if i == j:
			continue
		g[e[j][0] - 1].append(e[j][1])
		g[e[j][1] - 1].append(e[j][0])
	visited = [0] * n
	visited[0] = 1
	q = [1]
	while len(q) > 0:
		a = q.pop(0)
		visited[a - 1] = 1
		for k in g[a - 1]:
			if visited[k - 1] == 0:
				q += [k]
	if sum(visited) != n:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
l = [list(map(int, input().split())) for _ in range(M)]
g = [[0] * N for _ in range(N)]
for (i, j) in l:
	g[i - 1][j - 1] = 1
	g[j - 1][i - 1] = 1

def dfs(n):
	v[n - 1] = 1
	for n2 in range(1, N + 1):
		if g[n - 1][n2 - 1] == 1 and v[n2 - 1] == 0:
			dfs(n2)
r = 0
for (i, j) in l:
	g[i - 1][j - 1] = 0
	g[j - 1][i - 1] = 0
	v = [0] * N
	dfs(i)
	if sum(v) != N:
		r += 1
	g[i - 1][j - 1] = 1
	g[j - 1][i - 1] = 1
print(r)


from collections import deque
(number, m) = list(map(int, input().split()))
h = deque([])
for _ in range(m):
	l = list(map(int, input().split()))
	h.append(l)
count = 0
for i in range(m):
	if i != 0:
		h.append([a1, b1])
	(a1, b1) = h.popleft()
	g = [[] for _ in range(number)]
	for (a, b) in h:
		g[a - 1].append(b)
		g[b - 1].append(a)
	q = deque([a1])
	pre = [0] * number
	pre[a1 - 1] = 1
	while q:
		now = q.popleft()
		for n in g[now - 1]:
			if pre[n - 1] == 0:
				q.append(n)
				pre[n - 1] = 1
			else:
				continue
	if sum(pre) != number:
		count += 1
print(count)


def find(x):
	if par[x] < 0:
		return x
	else:
		tank = []
		while par[x] >= 0:
			tank.append(x)
			x = par[x]
		for elt in tank:
			par[elt] = x
		return x

def unite(x, y):
	x = find(x)
	y = find(y)
	if x == y:
		return False
	else:
		if par[x] > par[y]:
			(x, y) = (y, x)
		par[x] += par[y]
		par[y] = x
		return True

def same(x, y):
	return find(x) == find(y)

def size(x):
	return -par[find(x)]
(n, m) = list(map(int, input().split()))
edge = []
for _ in range(m):
	(a, b) = list(map(int, input().split()))
	(a, b) = (a - 1, b - 1)
	edge.append([a, b])
ans = 0
for j in range(m):
	par = [-1] * n
	cnt = 0
	for p in range(m):
		if p == j:
			continue
		e = edge[p]
		unite(e[0], e[1])
	for k in range(n):
		if par[k] < 0:
			cnt += 1
	if cnt >= 2:
		ans += 1
print(ans)


(n, m) = list(map(int, input().split()))
data = [list(map(int, input().split())) for i in range(m)]

def dfs(pos):
	if visit[pos] == 1:
		return
	visit[pos] = 1
	for i in range(n):
		if graph[pos][i] == 1:
			dfs(i)
count = 0
for hen in range(m):
	graph = [[0] * n for i in range(n)]
	visit = [0] * n
	for i in range(m):
		pos1 = data[i][0] - 1
		pos2 = data[i][1] - 1
		if i != hen:
			graph[pos1][pos2] = 1
			graph[pos2][pos1] = 1
	dfs(0)
	connected = True
	for i in range(n):
		if visit[i] == 0:
			connected = False
	if not connected:
		count += 1
print(count)


(N, M) = map(int, input().split())
to1 = [[0] for i in range(N)]
ab = [[0, 0] for i in range(M)]
for i in range(M):
	(ab[i][0], ab[i][1]) = map(int, input().split())
	to1[ab[i][0] - 1].append(ab[i][1] - 1)
	to1[ab[i][1] - 1].append(ab[i][0] - 1)
ans = 0

def DFS(n):
	nonlocal v
	if v[n] == 1:
		return
	v[n] = 1
	for i in to1[n]:
		DFS(i)
for i in range(M):
	v = [0] * N
	p = ab[i]
	p[0] -= 1
	p[1] -= 1
	to1[p[0]].remove(p[1])
	to1[p[1]].remove(p[0])
	DFS(0)
	if sum(v) != N:
		ans += 1
	to1[p[0]].append(p[1])
	to1[p[1]].append(p[0])
print(ans)


def i1():
	return int(input())

def i2():
	return [int(i) for i in input().split()]
[n, m] = i2()
e = [[0 for i in range(n)] for j in range(n)]
xx = []
for i in range(m):
	x = i2()
	x[0] -= 1
	x[1] -= 1
	xx.append(x)
	e[x[0]][x[1]] = 1
	e[x[1]][x[0]] = 1
d = [0 for i in range(n)]

def dfs(v):
	d[v] = 1
	for i in range(n):
		if e[v][i] == 1 and d[i] == 0:
			dfs(i)
a = 0
for i in xx:
	e[i[0]][i[1]] = 0
	e[i[1]][i[0]] = 0
	dfs(0)
	if 0 in d:
		a += 1
	d = [0 for j in range(n)]
	e[i[0]][i[1]] = 1
	e[i[1]][i[0]] = 1
print(a)


(N, M) = map(int, input().split())
AB = [list(map(int, input().split())) for i in range(M)]
r = 0
for m in range(M):
	c = [[] for i in range(N)]
	for (i, (a, b)) in enumerate(AB):
		if i != m:
			c[a - 1].append(b - 1)
			c[b - 1].append(a - 1)
	q = [0]
	v = [1] + [0] * (N - 1)
	while q:
		p = q.pop()
		for n in c[p]:
			if v[n] == 0:
				v[n] = 1
				q.append(n)
	if 0 in v:
		r += 1
print(r)


(N, M) = map(int, input().split())
A = [list(map(int, input().split())) for i in range(M)]
B = [[] for i in range(N)]
P = [0] * N
for (a, b) in A:
	B[a - 1].append(b - 1)
	B[b - 1].append(a - 1)
from collections import deque

def bfs(x):
	q = deque()
	q.append(x)
	while len(q):
		x = q.popleft()
		if P[x] == 0:
			for i in B[x]:
				q.append(i)
				P[x] = 1
ans = 0
for (a, b) in A:
	P = [0] * N
	B[a - 1].remove(b - 1)
	B[b - 1].remove(a - 1)
	bfs(0)
	if P != [1] * N:
		ans += 1
	B[a - 1].append(b - 1)
	B[b - 1].append(a - 1)
print(ans)


import math
from math import gcd, pi, sqrt
INF = float('inf')
import sys
sys.setrecursionlimit(10 ** 6)
import itertools
from collections import Counter, deque

def i_input():
	return int(input())

def i_map():
	return list(map(int, input().split()))

def i_list():
	return list(i_map())

def i_row(N):
	return [i_input() for _ in range(N)]

def i_row_list(N):
	return [i_list() for _ in range(N)]

def s_input():
	return input()

def s_map():
	return input().split()

def s_list():
	return list(s_map())

def s_row(N):
	return [s_input for _ in range(N)]

def s_row_str(N):
	return [s_list() for _ in range(N)]

def s_row_list(N):
	return [list(s_input()) for _ in range(N)]

def main():
	(n, m) = i_map()
	ab = [i_list() for i in range(m)]

	def dfs(table):
		visited = [1]
		que = [1]
		while que != []:
			now = que[0]
			del que[0]
			for (index, e) in enumerate(table[now]):
				if (e == 1) & (index not in visited):
					visited.append(index)
					que.append(index)
		if len(visited) == n:
			return 0
		else:
			return 1
	ans = 0
	for i in range(m):
		graph = ab.copy()
		del graph[i]
		table = [[0] * (n + 1) for i in range(n + 1)]
		for (a, b) in graph:
			table[a][b] = 1
			table[b][a] = 1
		ans += dfs(table)
	print(ans)

def __starting_point():
	main()
__starting_point()


class union_find:

	def __init__(self, n):
		self.n = n
		self.par = [i for i in range(n + 1)]
		self.rank = [0] * (n + 1)

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if self.rank[x] < self.rank[y]:
			self.par[x] = y
		else:
			self.par[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[y] += 1

	def same(self, x, y):
		return self.find(x) == self.find(y)
(n, m) = map(int, input().split())
uf = union_find(n)
ans = 0
s = []
for _ in range(m):
	a = list(map(int, input().split()))
	s.append(a)
	uf.union(a[0], a[1])
for e in range(m):
	uf1 = union_find(n)
	ch = 0
	for d in range(m):
		if d != e:
			uf1.union(s[d][0], s[d][1])
	for i in range(1, n):
		for j in range(i + 1, n + 1):
			if not uf1.same(i, j):
				ch += 1
	if ch > 0:
		ans += 1
print(ans)


from collections import deque
(n, m) = list(map(int, input().split()))
graph = [[] for i in range(n)]
for i in range(m):
	(u, v) = list(map(int, input().split()))
	u -= 1
	v -= 1
	graph[u].append([i, v])
	graph[v].append([i, u])
cnt = 0
for i in range(m):
	d = deque()
	d.append(0)
	visited = [False] * n
	visited[0] = True
	while d:
		cf = d.pop()
		for (ci, ct) in graph[cf]:
			if ci == i:
				continue
			if not visited[ct]:
				d.append(ct)
				visited[ct] = True
	if False in visited:
		cnt += 1
print(cnt)


(n, m) = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(m)]

def find(x):
	if root[x] < 0:
		return x
	else:
		root[x] = find(root[x])
		return root[x]

def unit(x, y):
	gx = find(x)
	gy = find(y)
	if gx == gy:
		return
	if root[gx] > root[gy]:
		(gx, gy) = (gy, gx)
	root[gx] += root[gy]
	root[gy] = gx
cnt = 0
for i in range(m):
	root = [-1] * n
	for j in range(m):
		if i == j:
			continue
		unit(AB[j][0] - 1, AB[j][1] - 1)
	roots = [i for i in root if i < 0]
	cnt += len(roots) != 1
print(cnt)


(n, m) = map(int, input().split())
X = []
M = [[] for _ in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	X.append([a - 1, b - 1])
	M[a - 1].append(b - 1)
	M[b - 1].append(a - 1)
ans = 0

def dfs(x, se):
	visited[x] = 1
	for m in M[x]:
		if se != {x, m} and visited[m] == 0:
			dfs(m, se)
for i in range(m):
	visited = [0] * n
	dfs(0, set(X[i]))
	if 0 in visited:
		ans += 1
print(ans)


import copy
import sys
sys.setrecursionlimit(10 ** 7)
(N, M) = map(int, input().split())
G = [[] for _ in range(N)]
side = []
for _ in range(M):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	G[a].append(b)
	G[b].append(a)
	side.append((a, b))

def dfs(v, G):
	seen[v] = True
	for next_v in G[v]:
		if seen[next_v] == True:
			continue
		dfs(next_v, G)
bridge = 0
for (a, b) in side:
	Gc = copy.deepcopy(G)
	Gc[a].remove(b)
	Gc[b].remove(a)
	seen = [False] * N
	cnt = 0
	for s in range(N):
		if seen[s] == True:
			continue
		cnt += 1
		dfs(s, Gc)
	if cnt >= 2:
		bridge += 1
print(bridge)


(N, M) = map(int, input().split())
E = [[False for i in range(N)] for j in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	E[a - 1][b - 1] = True
	E[b - 1][a - 1] = True

def search_leaf(edge_list):
	for i in range(N):
		if edge_list[i].count(True) == 1:
			return i
	return -1
ans = 0
for _ in range(M):
	V = search_leaf(E)
	if V == -1:
		break
	main_land = E[V].index(True)
	E[V][main_land] = E[main_land][V] = False
	ans += 1
print(ans)


(N, M) = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(M)]

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
ans = 0
for i in range(M):
	uf = UnionFind(N)
	for j in range(M):
		if i == j:
			continue
		(a, b) = ab[j]
		uf.union(a - 1, b - 1)
	ans += uf.group_count() > 1
print(ans)


import collections
(n, m) = map(int, input().split())
ab = []
v = [[] for _ in range(n + 1)]
for _ in range(m):
	(a, b) = map(int, input().split())
	ab.append([a, b])
	v[a].append(b)
	v[b].append(a)
ans = 0
for (a, b) in ab:
	visited = set()
	q = collections.deque()
	q.append(1)
	visited.add(1)
	while q:
		c = q.pop()
		for i in v[c]:
			if i in visited:
				continue
			if a == i and b == c or (a == c and b == i):
				continue
			q.append(i)
			visited.add(i)
	if len(visited) != n:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
E = [list(map(int, input().split())) for _ in range(M)]
from collections import defaultdict
ans = 0
for i in range(M):
	d = defaultdict(list)
	for j in range(M):
		if i != j:
			d[E[j][0]].append(E[j][1])
			d[E[j][1]].append(E[j][0])
	f = defaultdict(lambda : 0)
	f[1] = 1
	que = d[1]
	while len(que) > 0:
		tmp = []
		for q in que:
			if f[q] == 0:
				f[q] = 1
				tmp += d[q]
		que = tmp
	if len(f.keys()) < N:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
edges = [list(map(int, input().split())) for i in range(m)]
count = 0
for x in edges:
	l = list(range(n))
	for y in edges:
		if y != x:
			l = [l[y[0] - 1] if l[i] == l[y[1] - 1] else l[i] for i in range(n)]
	if len(set(l)) != 1:
		count += 1
print(count)


def BFS(n, path):
	check = [0] * n
	check[0] = 1
	Que = [0]
	while Que:
		u = Que.pop(-1)
		for v in path[u]:
			if check[v] == 0:
				check[v] = 1
				Que.append(v)
	if check != [1] * n:
		return 1
	else:
		return 0
(N, M) = map(int, input().split())
A = []
B = []
for i in range(M):
	(a, b) = map(int, input().split())
	A += [a - 1]
	B += [b - 1]
ans = 0
for i in range(M):
	edges = [[] for i in range(N)]
	for j in range(M):
		if j != i:
			edges[A[j]] += [B[j]]
			edges[B[j]] += [A[j]]
	ans += BFS(N, edges)
print(ans)


(N, M) = list(map(int, input().split()))
AB = [tuple(map(int, input().split())) for _ in range(M)]

def find(x):
	if par[x] == x:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	x = find(x)
	y = find(y)
	if x == y:
		return 0
	par[x] = y
cnt = 0
for i in range(M):
	par = [i for i in range(N + 1)]
	k = 0
	for (a, b) in AB:
		if k != i:
			unite(a, b)
		k += 1
	res = []
	for j in range(1, N + 1):
		res.append(find(j))
	if len(set(res)) >= 2:
		cnt += 1
print(cnt)


(N, M) = map(int, input().split())
(s, t) = ([], [[] for j in range(N)])
for i in range(M):
	(xx, yy) = map(int, input().split())
	(x, y) = (xx - 1, yy - 1)
	s += [[x, y]]
	t[x].append(y)
	t[y].append(x)

def loop(q, j, k):
	w.append(q)
	for kk in t[q]:
		if kk not in w and (not (q == j and kk == k)) and (not (q == k and kk == j)):
			loop(kk, j, k)
ans = 0
for ii in range(M):
	w = []
	[j, k] = s[ii]
	loop(j, j, k)
	if len(w) != N:
		ans += 1
print(ans)


import copy
(N, M) = map(int, input().split())
a = [0] * M
b = [0] * M
bridge = 0
for i in range(0, M):
	(a[i], b[i]) = map(int, input().split())
for i in range(0, M):
	V = {1}
	while True:
		X = copy.copy(V)
		v = len(V)
		for j in X:
			for k in range(0, M):
				if a[k] == j and k != i:
					V.add(b[k])
				elif b[k] == j and k != i:
					V.add(a[k])
		test = len(V)
		if test == N:
			break
		elif test == v:
			bridge += 1
			break
print(bridge)


(n, m) = map(int, input().split())
ab = [list(map(int, input().split())) for i in range(m)]
cnt = 0
for x in ab:
	ls = list(range(n))
	for y in ab:
		if y != x:
			for i in range(n):
				ls = [ls[y[0] - 1] if ls[i] == ls[y[1] - 1] else ls[i] for i in range(n)]
	if len(set(ls)) != 1:
		cnt += 1
print(cnt)


(N, M) = [int(x) for x in str(input()).split()]
E = []
for i in range(M):
	E.append([int(x) for x in str(input()).split()])

def dfs(u):
	visited[u] = True
	for j in adj[u]:
		if visited[j] == False:
			dfs(j)
count = 0
for i in range(M):
	P = E[:i] + E[i + 1:]
	visited = [False for x in range(0, N + 1)]
	adj = [[0] for k in range(0, N + 1)]
	for j in range(1, N + 1):
		r = []
		for l in P:
			if l[0] == j:
				r.append(l[1])
			elif l[1] == j:
				r.append(l[0])
		adj[j] = r
	dfs(1)
	if sum(visited) != N:
		count += 1
print(count)


(n, m) = map(int, input().split())
edges = [list(map(int, input().split())) for _ in range(m)]
ans = 0
for edge_i in edges:
	check_list = [i for i in range(n)]
	for edge_j in edges:
		if edge_i != edge_j:
			check_list = [check_list[edge_j[0] - 1] if check_list[i] == check_list[edge_j[1] - 1] else check_list[i] for i in range(n)]
	if len(set(check_list)) != 1:
		ans += 1
print(ans)


(n, m) = map(int, input().split())

def find(x):
	if par[x] < 0:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def union(x, y):
	(x, y) = (find(x), find(y))
	if x != y:
		if x > y:
			(x, y) = (y, x)
		par[x] += par[y]
		par[y] = x
M = []
for i in range(m):
	(x, y) = map(int, input().split())
	M.append([x - 1, y - 1])
ans = 0
for i in range(m):
	X = M[:i] + M[i + 1:]
	par = [-1] * n
	for x in X:
		union(x[0], x[1])
	if [p < 0 for p in par].count(1) > 1:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
a = [list(map(int, input().split())) for i in range(m)]
b = [[] for i in range(n)]
for i in range(m):
	b[a[i][0] - 1] += [a[i][1] - 1]
	b[a[i][1] - 1] += [a[i][0] - 1]

def f(x, p, q):
	c[x] = True
	for i in b[x]:
		if c[i] == False:
			if i == p and x == q or (i == q and x == p):
				continue
			else:
				f(i, p, q)
d = 0
for i in range(m):
	c = [False] * n
	f(a[i][0] - 1, a[i][0] - 1, a[i][1] - 1)
	if c != [True] * n:
		d += 1
print(d)


(n, m) = map(int, input().split())
v = []
for i in range(m):
	(a, b) = map(int, input().split())
	v.append((a - 1, b - 1))

def dfs(x):
	check[x] = True
	for i in graph[x]:
		if not check[i]:
			dfs(i)
ans = 0
for i in range(m):
	graph = [[] for i in range(n)]
	for j in range(m):
		if j != i:
			graph[v[j][0]].append(v[j][1])
			graph[v[j][1]].append(v[j][0])
	check = [False] * n
	dfs(0)
	for j in check:
		if not j:
			ans += 1
			break
print(ans)


(N, M) = map(int, input().split())
G = []
for i in range(M):
	G.append(list(map(int, input().split())))

def dfs(E, visited, v):
	visited[v] = 1
	for u in E[v]:
		if not visited[u]:
			dfs(E, visited, u)
	return sum(visited)
ans = 0
for i in range(M):
	Gtmp = G[:]
	del Gtmp[i:i + 1]
	E = [set() for _ in range(N + 1)]
	for g in Gtmp:
		E[g[0]].add(g[1])
		E[g[1]].add(g[0])
	visited = [0] * (N + 1)
	if dfs(E, visited, 1) < N:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
G = [[0] * n for i in range(n)]
V = [0 for i in range(n)]
A = []
B = []
for i in range(m):
	(a, b) = map(int, input().split())
	A.append(a - 1)
	B.append(b - 1)
	G[a - 1][b - 1] = G[b - 1][a - 1] = 1

def dfs(v):
	V[v] = 1
	for v2 in range(n):
		if G[v][v2] == 1 and V[v2] == 0:
			dfs(v2)
ans = 0
for i in range(m):
	G[A[i]][B[i]] = G[B[i]][A[i]] = 0
	V = [0 for i in range(n)]
	dfs(0)
	if sum(V) != n:
		ans += 1
	G[A[i]][B[i]] = G[B[i]][A[i]] = 1
print(ans)


(n, m) = map(int, input().split())
ab = [list(map(int, input().split())) for i in range(m)]
ad = [[0] * n for i in range(n)]
for x in ab:
	ad[x[0] - 1][x[1] - 1] = 1
	ad[x[1] - 1][x[0] - 1] = 1
nodes = [0] * n
ans = 0
flag = True
while flag:
	flag = False
	for i in range(n):
		if nodes[i] == 0 and sum(ad[i]) == 1:
			ans += 1
			nodes[i] = 1
			flag = True
			for j in range(n):
				if ad[i][j] == 1:
					ad[j][i] = 0
print(ans)


from collections import deque
(N, M) = map(int, input().split())
h = [[] * N for _ in range(N)]
AB = []
for _ in range(M):
	(a, b) = list(map(int, input().split()))
	a -= 1
	b -= 1
	h[a].append(b)
	h[b].append(a)
	AB.append([a, b])
ans = 0
for i in range(M):
	(a, b) = AB[i]
	h[a].remove(b)
	h[b].remove(a)
	fl = [False] * N
	q = deque([0])
	while q:
		t = q.popleft()
		if fl[t]:
			continue
		fl[t] = True
		for tt in h[t]:
			q.append(tt)
	if not all(fl):
		ans += 1
	h[a].append(b)
	h[b].append(a)
print(ans)


import sys
readline = sys.stdin.readline
(N, M) = map(int, readline().split())
bridges = [None] * M
G = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, readline().split())
	G[a - 1].append(b - 1)
	G[b - 1].append(a - 1)
	bridges[i] = (a - 1, b - 1)
from collections import deque
ans = 0
for i in range(M):
	q = deque([])
	q.append(0)
	seen = set()
	while q:
		v = q.popleft()
		if v in seen:
			continue
		seen.add(v)
		for child in G[v]:
			if (v, child) == bridges[i] or (child, v) == bridges[i]:
				continue
			q.append(child)
	if len(seen) != N:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
g = [[] for i in range(n)]
ab = []
for k in range(m):
	(i, j) = map(int, input().split())
	(i, j) = (i - 1, j - 1)
	g[i].append(j)
	g[j].append(i)
	ab.append((i, j))
c = 0
for i in range(m):
	visited = [1] + [0] * (n - 1)
	stack = [0]
	while stack:
		cur = stack.pop()
		for j in g[cur]:
			if ab[i] in [(cur, j), (j, cur)]:
				continue
			if visited[j] == 0:
				visited[j] = 1
				stack.append(j)
	if 0 in visited:
		c += 1
print(c)


class UnionFind:

	def __init__(self, N):
		self.N = N
		self.parent = [-1] * N

	def root(self, i):
		if self.parent[i] < 0:
			return i
		r = self.root(self.parent[i])
		self.parent[i] = r
		return r

	def unite(self, i, j):
		i = self.root(i)
		j = self.root(j)
		if i == j:
			return
		if i > j:
			(i, j) = (j, i)
		self.parent[i] += self.parent[j]
		self.parent[j] = i

	def same(self, i, j):
		return self.root(i) == self.root(j)

	def size(self, i):
		return -self.parent[self.root(i)]

	def roots(self):
		return [self.root(i) for i in range(self.N)]

	def groupcount(self):
		return len(set(self.roots()))
(N, M) = map(int, input().split())
edges = [[int(x) - 1 for x in input().split()] for _ in range(M)]
ans = 0
for i in range(M):
	forest = UnionFind(N)
	for (i, j) in edges[:i] + edges[i + 1:]:
		forest.unite(i, j)
	if forest.groupcount() != 1:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
h = [list(map(int, input().split())) for i in range(M)]
a = 0

def s(n, m, l):
	for j in range(n, m):
		if l[h[j][0] - 1] or l[h[j][1] - 1]:
			(l[h[j][0] - 1], l[h[j][1] - 1]) = (1, 1)
	return l
for i in range(M):
	l = [1] + [0] * (N - 1)
	for _ in range(N - 1):
		l = s(0, i, l)
		l = s(i + 1, M, l)
	if 0 in l:
		a += 1
print(a)


class UnionFind:

	def __init__(self, n):
		self.nodes = n
		self.parents = [i for i in range(n)]
		self.sizes = [1] * n
		self.rank = [0] * n

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				self.sizes[y] += self.sizes[x]
				self.parents[x] = y
			else:
				self.sizes[x] += self.sizes[y]
				self.parents[y] = x
				if self.rank[x] == self.rank[y]:
					self.rank[x] += 1

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def get_parents(self):
		for n in range(self.nodes):
			self.find(n)
		return self.parents
adj = []
(N, M) = map(int, input().split())
for m in range(M):
	(a, b) = map(int, input().split())
	adj.append([a - 1, b - 1])
ans = 0
for i in range(M):
	uf = UnionFind(N)
	for j in range(M):
		if i == j:
			continue
		uf.unite(*adj[j])
	if len(set(uf.get_parents())) != 1:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
e = [list(map(int, input().split())) for _ in range(m)]
c = 0
for x in e:
	l = list(range(n))
	for y in e:
		if y != x:
			l = [l[y[0] - 1] if l[i] == l[y[1] - 1] else l[i] for i in range(n)]
	if len(set(l)) != 1:
		c += 1
print(c)


(n, m) = map(int, input().split())
x = []
d = [[] for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	d[a - 1].append(b - 1)
	d[b - 1].append(a - 1)
	x.append((a - 1, b - 1))
ans = 0
for i in x:
	t = set([i[0]])
	r = set()
	while len(t):
		o = t.pop()
		for j in d[o]:
			if j not in r and len(set([o, j]) & set([i[0], i[1]])) != 2:
				r.add(j)
				t.add(j)
	if len(r) != n:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
from collections import defaultdict
d = defaultdict(list)
B = []
for _ in range(m):
	(a1, a2) = list(map(int, input().split()))
	B.append([a1, a2])
	d[a1].append(a2)
	d[a2].append(a1)

def dfs(a, conn):
	memo[a] = 1
	for c in conn:
		if memo[c] == 0:
			dfs(c, d[c])
cnt = 0
for b in B:
	(a1, a2) = b
	memo = [0] * (n + 1)
	conn = set(d[a1]) - set([a2])
	dfs(a1, conn)
	if memo.count(1) != n:
		cnt += 1
print(cnt)


import copy
(N, M) = map(int, input().split())
l = []
for i in range(M):
	l.append(list(map(int, input().split())))

def bfs(l, tmp, came):
	t = []
	for n in tmp:
		for s in l:
			if s[0] == n and s[1] not in came:
				t.append(s[1])
				came.append(s[1])
			elif s[1] == n and s[0] not in came:
				t.append(s[0])
				came.append(s[0])
	if t == []:
		came = set(came)
		return came
	else:
		return bfs(l, t, came)
ans = 0
for i in range(M):
	x = copy.copy(l)
	x.pop(i)
	a = bfs(x, [1], [1])
	if len(a) < N:
		ans += 1
print(ans)


import sys
from io import StringIO
import unittest
from collections import deque

class TestClass(unittest.TestCase):

	def assertIO(self, input, output):
		(stdout, stdin) = (sys.stdout, sys.stdin)
		(sys.stdout, sys.stdin) = (StringIO(), StringIO(input))
		resolve()
		sys.stdout.seek(0)
		out = sys.stdout.read()[:-1]
		(sys.stdout, sys.stdin) = (stdout, stdin)
		self.assertEqual(out, output)

	def test_入力例_1(self):
		input = '7 7\n1 3\n2 7\n3 4\n4 5\n4 6\n5 6\n6 7'
		output = '4'
		self.assertIO(input, output)

	def test_入力例_2(self):
		input = '3 3\n1 2\n1 3\n2 3'
		output = '0'
		self.assertIO(input, output)

	def test_入力例_3(self):
		input = '6 5\n1 2\n2 3\n3 4\n4 5\n5 6'
		output = '5'
		self.assertIO(input, output)

def resolve():
	(N, M) = list(map(int, input().split()))
	AB = [list(map(int, input().split())) for _ in range(M)]
	ans = 0
	for i in range(M):
		Target = AB[:]
		Target.pop(i)
		G = [[i + 1, 0] for i in range(N)]
		for ab in Target:
			(a, b) = ab
			G[a - 1][1] += 1
			G[b - 1][1] += 1
			G[a - 1].append(b)
			G[b - 1].append(a)
		F = [False] * N
		Q = deque()
		Q.append(1)
		F[0] = True
		while Q:
			p = Q.pop()
			if G[p - 1][1] == 0:
				continue
			for np in G[p - 1][2:]:
				if F[np - 1]:
					continue
				Q.append(np)
				F[np - 1] = True
		for f in F:
			if f == False:
				ans += 1
				break
	print(ans)

def __starting_point():
	resolve()
__starting_point()


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = [int(i) for i in input().split()]
ABS = [[int(i) for i in input().split()] for _ in range(M)]
cnt = 0
for i in range(M):
	uf = UnionFind(N + 1)
	for (a, b) in [*ABS[:i], *ABS[i + 1:]]:
		uf.union(a, b)
	if uf.group_count() > 2:
		cnt += 1
print(cnt)


(n, m) = map(int, input().split())
data = []
G = [[] for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	data.append((a - 1, b - 1))
	G[a - 1].append(b - 1)
	G[b - 1].append(a - 1)

def dfs(v, seen):
	if seen[v]:
		return
	seen[v] = True
	for nv in G[v]:
		dfs(nv, seen)
cnt = 0
for i in range(m):
	(ra, rb) = data[i]
	G[ra].remove(rb)
	G[rb].remove(ra)
	seen = [False] * n
	dfs(0, seen)
	cnt += sum(seen) != n
	G[ra].append(rb)
	G[rb].append(ra)
print(cnt)


(n, m) = map(int, input().split())
lists = []
for _ in range(m):
	(a, b) = map(int, input().split())
	lists.append([a, b])
answer = 0
for some in range(m):
	ans = 0
	for i in range(1, n + 1):
		cnt = 0
		for _ in lists:
			if _[0] == i or _[1] == i:
				cnt += 1
				index = lists.index(_)
		if cnt == 1:
			ans += 1
			del lists[index]
		else:
			ans += 0
			continue
	answer += ans
print(answer)


(N, M) = map(int, input().split())
ab = [list(map(int, input().split())) for i in range(M)]
ans = 0
for i in ab:
	vertex = list(range(N))
	for j in ab:
		if i != j:
			vertex = [vertex[j[0] - 1] if vertex[k] == vertex[j[1] - 1] else vertex[k] for k in range(N)]
	if len(set(vertex)) != 1:
		ans += 1
print(ans)


f = lambda : map(int, input().split())
(n, m) = f()
lt = []
ll = [[0] * n for _ in range(n)]
for _ in range(m):
	(a, b) = f()
	a -= 1
	b -= 1
	lt += [(a, b)]
	ll[a][b] = ll[b][a] = 1

def dfs(x):
	if lv[x] > 0:
		return
	lv[x] = 1
	for i in range(n):
		if ll[i][x] > 0:
			dfs(i)
c = 0
for (a, b) in lt:
	ll[a][b] = ll[b][a] = 0
	lv = [0] * n
	dfs(0)
	if sum(lv) < n:
		c += 1
	ll[a][b] = ll[b][a] = 1
print(c)


from collections import deque
(n, m) = map(int, input().split())
l = [list(map(int, input().split())) for _ in range(m)]
ans = 0

def bfs(start_node, color_id):
	nonlocal color, d
	q = deque([start_node])
	d[start_node] = 0
	color[start_node] = color_id
	while len(q) != 0:
		u = q.popleft()
		for v in adjl[u]:
			if color[v] == NIL:
				d[v] = d[u] + 1
				color[v] = color_id
				q.append(v)
for k in range(1, m + 1):
	adjl = [[] for _ in range(n + 1)]
	for i in range(1, m + 1):
		if i == k:
			continue
		(s, t) = l[i - 1]
		adjl[s].append(t)
		adjl[t].append(s)
	NIL = -1
	d = [-1 for i in range(n + 1)]
	color = [NIL for i in range(n + 1)]
	color_id = 0
	for u in range(1, n + 1):
		if color[u] == NIL:
			color_id += 1
			bfs(u, color_id)
	if len(set(color)) >= 3:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
g = [list() for _ in range(n + 1)]
side = [list(map(int, input().split())) for i in range(m)]
for (a, b) in side:
	g[a].append(b)
	g[b].append(a)
cnt = 0

def dfs(x, s):
	ed[x - 1] = 1
	for i in g[x]:
		if s != {x, i} and ed[i - 1] == 0:
			dfs(i, s)
cnt = 0
for i in range(m):
	ed = [0] * n
	dfs(1, set(side[i]))
	if 0 in ed:
		cnt += 1
print(cnt)


(n, m) = map(int, input().split())
par = [i for i in range(n + 1)]

def find(x):
	if par[x] == x:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def same(x, y):
	return find(x) == find(y)

def unite(x, y):
	x = find(x)
	y = find(y)
	if x == y:
		return 0
	par[x] = y
ls = [list(map(int, input().split())) for _ in range(m)]
ans = 0
for i in ls:
	for k in ls:
		if i != k:
			[a, b] = k
			unite(a, b)
	flag = True
	for p in range(1, n + 1):
		for q in range(1, n + 1):
			if not same(p, q):
				flag = False
				break
		if flag == False:
			break
	if flag == False:
		ans += 1
	par = [i for i in range(n + 1)]
print(ans)


def dfs(V, E):
	s[V - 1] = 1
	for i in Ren[V - 1]:
		if E != {V, i} and s[i - 1] == 0:
			dfs(i, E)
(N, M) = map(int, input().split())
Edge = [list(map(int, input().split())) for i in range(M)]
Ren = [[] for i in range(N)]
for (a, b) in Edge:
	Ren[a - 1].append(b)
	Ren[b - 1].append(a)
ans = 0
for i in Edge:
	s = [0] * N
	dfs(1, set(i))
	if 0 in s:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
edges = [list(map(int, input().split())) for i in range(M)]
ans = 0
for x in edges:
	l = list(range(N))
	for y in edges:
		if y != x:
			l = [l[y[0] - 1] if l[i] == l[y[1] - 1] else l[i] for i in range(N)]
	if len(set(l)) != 1:
		ans += 1
print(ans)


import copy

def main():
	(N, M) = [int(n) for n in input().split(' ')]
	edges = [[] for i in range(N)]
	r = []
	for i in range(M):
		(a, b) = [int(x) for x in input().split(' ')]
		edges[a - 1].append(b - 1)
		edges[b - 1].append(a - 1)
		r.append([a - 1, b - 1])
	cnt = 0
	for i in range(len(r)):
		if not isConnected(edges, r[i]):
			cnt += 1
	print(cnt)

def isConnected(edges, remove_edge):
	n_v = len(edges)
	checked = [0] * n_v
	to_check = [0]
	e = copy.deepcopy(edges)
	e[remove_edge[0]].remove(remove_edge[1])
	e[remove_edge[1]].remove(remove_edge[0])
	while len(to_check) > 0:
		checking = to_check.pop(0)
		checked[checking] = 1
		for i in e[checking]:
			if checked[i] == 1:
				continue
			else:
				to_check.append(i)
	if n_v == sum(checked):
		return True
	else:
		return False
main()


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.size = [1 for i in range(n)]

	def root(self, x):
		if self.parent[x] == x:
			return x
		else:
			self.parent[x] = self.root(self.parent[x])
			return self.parent[x]

	def unite(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x != y:
			self.parent[x] = y
			self.size[y] += self.size[x]

	def same(self, x, y):
		return self.root(x) == self.root(y)

	def count(self, x):
		return self.size[self.root(x)]
(N, M) = list(map(int, input().split()))
AB = [list([int(x) - 1 for x in input().split()]) for _ in range(M)]
ans = 0
for i in range(M):
	un = UnionFind(N)
	for j in range(M):
		if i != j:
			un.unite(AB[j][0], AB[j][1])
	if un.count(0) != N:
		ans += 1
print(ans)


from collections import Counter
(N, M) = map(int, input().split())

class UnionFind:

	def __init__(self, N):
		self.root = list(range(N + 1))
		self.size = [1] * (N + 1)

	def __getitem__(self, x):
		root = self.root
		while root[x] != x:
			root[x] = root[root[x]]
			x = root[x]
		return x

	def merge(self, x, y):
		x = self[x]
		y = self[y]
		if x == y:
			return
		(sx, sy) = (self.size[x], self.size[y])
		if sx < sy:
			(x, y) = (y, x)
			(sx, sy) = (sy, sx)
		self.root[y] = x
		self.size[x] += sy
(A, B) = ([], [])
for i in range(M):
	(a, b) = map(int, input().split())
	A.append(a)
	B.append(b)
count = 0
for i in range(M):
	uni = UnionFind(N)
	for j in range(M):
		if j == i:
			continue
		uni.merge(A[j], B[j])
	roots = [uni[x] for x in uni.root[1:]]
	counter = Counter(roots)
	if len(counter) > 1:
		count += 1
print(count)


(N, M) = map(int, input().split())
ABs = []
for i in range(M):
	(a, b) = map(int, input().split())
	(a, b) = (a - 1, b - 1)
	ABs.append((a, b))
r = 0
for i in range(M):
	E = [[] for i in range(N)]
	for j in range(M):
		if j == i:
			continue
		(a, b) = ABs[j]
		E[a].append(b)
		E[b].append(a)
	V = [False] * N
	V[0] = True
	q = [0]
	while q:
		c = q.pop()
		ns = E[c]
		for n in ns:
			if not V[n]:
				V[n] = True
				q.append(n)
	if not all(V):
		r += 1
print(r)


import sys
from collections import deque
input = sys.stdin.readline
(N, M) = map(int, input().split())
edges = [[] for _ in range(N)]
edge_set = set()
for _ in range(M):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	edges[a].append(b)
	edges[b].append(a)
	edge_set.add((a, b))
ans = 0
for (a, b) in edge_set:
	q = deque()
	q.append(0)
	visited = set()
	while q:
		p = q.popleft()
		if p in visited:
			continue
		visited.add(p)
		for np in edges[p]:
			if (p, np) == (a, b) or (np, p) == (a, b):
				continue
			q.append(np)
	if len(visited) != N:
		ans += 1
print(ans)


def dfs(s):
	global used, G
	used.add(s)
	for t in G[s]:
		if t not in used:
			dfs(t)
(N, M) = map(int, input().split())
es = []
G = [[] for i in range(N)]
for i in range(M):
	(a, b) = [int(i) - 1 for i in input().split()]
	G[a].append(b)
	G[b].append(a)
	es.append([a, b])
ans = 0
for (a, b) in es:
	G[a].remove(b)
	G[b].remove(a)
	used = set()
	dfs(0)
	if len(used) != N:
		ans += 1
	G[a].append(b)
	G[b].append(a)
print(ans)


class UnionFind:

	def __init__(self, n):
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x
(N, M) = map(int, input().split())
AB = []
for _ in range(M):
	AB.append(list(map(int, input().split())))
ans = 0
for i in range(M):
	if i == M - 1:
		ab = AB[:M - 1]
	else:
		ab = AB[:i] + AB[i + 1:]
	uf = UnionFind(N)
	for j in ab:
		uf.union(j[0] - 1, j[1] - 1)
	if uf.parents[uf.find(0)] != -N:
		ans += 1
print(ans)


(N, M) = map(int, input().split(' '))
ab = [list(map(lambda x: int(x) - 1, input().split(' '))) for x in range(M)]
p = [[False] * N for x in range(N)]
for a in ab:
	p[a[0]][a[1]] = True
	p[a[1]][a[0]] = True

def dfs(v):
	c[v] = True
	for i in range(N):
		if p[v][i] and (not c[i]):
			dfs(i)
s = 0
for a in ab:
	p[a[0]][a[1]] = False
	p[a[1]][a[0]] = False
	c = [False] * N
	dfs(a[0])
	if False in c:
		s += 1
	p[a[0]][a[1]] = True
	p[a[1]][a[0]] = True
print(s)


from collections import deque
from sys import stdin
input = stdin.readline
(N, M) = map(int, input().split())
neighbor = [[] for _ in range(N)]
A = [-1] * M
B = [-1] * M
for i in range(M):
	(a, b) = map(lambda x: int(x) - 1, input().split())
	A[i] = a
	B[i] = b
	neighbor[a].append(b)
	neighbor[b].append(a)
cnt = 0
for i in range(M):
	(a, b) = (A[i], B[i])
	neighbor[a].remove(b)
	neighbor[b].remove(a)
	visited = [False] * N
	queue = deque()
	queue.append(0)
	visited[0] = True
	while queue:
		x = queue.popleft()
		for z in neighbor[x]:
			if not visited[z]:
				visited[z] = True
				queue.append(z)
	if False in visited:
		cnt += 1
	neighbor[a].append(b)
	neighbor[b].append(a)
print(cnt)


(N, M) = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(M)]
ans = 0
for i in range(M):
	ab2 = ab[:i] + ab[i + 1:]
	connect = [[] for _ in range(N + 1)]
	for (a, b) in ab2:
		connect[a].append(b)
		connect[b].append(a)
	V = [-1] * (N + 1)
	V[0] = 0
	V[1] = 0
	q = [1]
	for j in q:
		for k in connect[j]:
			if V[k] == -1:
				V[k] = V[j] + 1
				q.append(k)
	for v in V[1:]:
		if v == -1:
			ans += 1
			break
print(ans)


def search(u, g, visited):
	if visited[u]:
		return
	visited[u] = True
	for v in g[u]:
		search(v, g, visited)

def resolve():
	(n, m) = map(int, input().split())
	edges = [list(map(int, input().split())) for _ in range(m)]
	ans = 0
	for i in range(m):
		g = [[] for _ in range(n)]
		for j in range(m):
			if i == j:
				continue
			(a, b) = edges[j]
			g[a - 1].append(b - 1)
			g[b - 1].append(a - 1)
		visited = [False] * n
		search(0, g, visited)
		if visited.count(True) != n:
			ans += 1
	print(ans)
resolve()


def dfs(bri1):
	for l in land[bri1 - 1]:
		if seen[l - 1] == 0 and (not (bri1 == bri[0] and l == bri[1])):
			seen[l - 1] = 1
			dfs(l)
(N, M) = map(int, input().split())
data = [0] * M
land = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	data[i] = [a, b]
	land[a - 1].append(b)
	land[b - 1].append(a)
cnt = 0
for i in range(M):
	bri = data[i]
	seen = [0] * N
	dfs(bri[0])
	if sum(seen) != N:
		cnt += 1
print(cnt)


class union_find:

	def __init__(self, n):
		self.root = [-1] * (n + 1)
		self.rank = [0] * (n + 1)
		self.siz = n

	def find_root(self, x):
		if self.root[x] < 0:
			return x
		else:
			self.root[x] = self.find_root(self.root[x])
			return self.root[x]

	def unite(self, x, y):
		x = self.find_root(x)
		y = self.find_root(y)
		if x == y:
			return
		elif self.rank[x] > self.rank[y]:
			self.root[x] += self.root[y]
			self.root[y] = x
		else:
			self.root[y] += self.root[x]
			self.root[x] = y
			if self.rank[x] == self.rank[y]:
				self.rank[y] += 1
		self.siz -= 1

	def same(self, x, y):
		return self.find_root(x) == self.find_root(y)

	def size(self):
		return self.siz
(n, m) = list(map(int, input().split()))
ab = []
for _ in range(m):
	ab.append(list(map(int, input().split())))
g = union_find(n)
ans = 0
for i in range(len(ab)):
	for j in range(len(ab)):
		if i == j:
			continue
		(a, b) = ab[j]
		g.unite(a, b)
	if g.size() != 1:
		ans += 1
	g = union_find(n)
print(ans)


def dps(now, i, j, arr, node):
	for x in arr[now]:
		if now == i and x == j or (now == j and x == i):
			continue
		if node[x] == 0:
			node[x] = 1
			dps(x, i, j, arr, node)
(N, M) = list(map(int, input().split()))
arr = [[] for i in range(N)]
for i in range(M):
	(a, b) = list(map(int, input().split()))
	arr[a - 1].append(b - 1)
	arr[b - 1].append(a - 1)
ans = 0
for (i, x) in enumerate(arr):
	for j in x:
		node = [0 for _ in range(N)]
		dps(0, i, j, arr, node)
		if sum(node) != N:
			ans += 1
print(ans // 2)


(n, m) = map(int, input().split())
(a, b, ans) = ([[] for _ in range(n)], [], 0)

def solve(v, aa, bb):
	visited[v] = True
	for n in a[v]:
		if not visited[n] and set([v, n]) != set([aa, bb]):
			solve(n, aa, bb)
for i in range(m):
	(x, y) = map(int, input().split())
	a[x - 1].append(y - 1)
	a[y - 1].append(x - 1)
	b.append((x - 1, y - 1))
for i in range(m):
	visited = [True] + [False] * (n - 1)
	(x, y) = b[i]
	solve(0, x, y)
	if visited != [True] * n:
		ans += 1
print(ans)


import copy
(N, M) = map(int, input().split())
N += 1
A = [[int(i) for i in input().split()] for i in range(M)]

def dfs(x):
	if vis[x]:
		return
	vis[x] = True
	for i in range(N):
		if G[x][i]:
			dfs(i)
cnt = 0
for i in range(M):
	vis = [False] * N
	A2 = copy.deepcopy(A)
	del A2[i]
	G = [[0] * N for i in range(N)]
	for (i, j) in A2:
		G[i][j] = 1
		G[j][i] = 1
	dfs(1)
	if any((vis[i] == False for i in range(1, N))):
		cnt += 1
print(cnt)


from collections import defaultdict

def dfs(i, used, dic, ng):
	for n in dic[i]:
		if n not in used and (i, n) != ng and ((n, i) != ng):
			used.add(n)
			dfs(n, used, dic, ng)
(N, M) = map(int, input().split())
dic = defaultdict(list)
lst = []
for _ in range(M):
	(a, b) = map(int, input().split())
	dic[a].append(b)
	dic[b].append(a)
	lst.append((a, b))
ret = 0
for (a, b) in lst:
	used = set()
	dfs(1, used, dic, (a, b))
	if len(used) != N:
		ret += 1
print(ret)


(N, M) = map(int, input().split())
E = [[int(x) - 1 for x in input().split()] for _ in range(M)]
ans = 0
for i in range(M):
	G = [set() for _ in range(N)]
	for j in range(M):
		if i == j:
			continue
		(a, b) = E[j]
		G[a].add(b)
		G[b].add(a)
	todo = [0]
	done = set()
	while todo:
		p = todo.pop()
		done.add(p)
		for np in G[p]:
			if not np in done:
				todo.append(np)
	if len(done) < N:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
node_list = [[0] * n for i in range(n)]
count = 0
for i in range(m):
	(a, b) = map(int, input().split())
	node_list[a - 1][b - 1] = 1
	node_list[b - 1][a - 1] = 1
flg = True
count = 0
while flg:
	flg = False
	for i in range(n):
		if node_list[i].count(1) == 1:
			count += 1
			j = node_list[i].index(1)
			node_list[i][j] = 0
			node_list[j][i] = 0
			flg = True
print(count)


import sys
sys.setrecursionlimit(10 ** 7)

def dfs(v, remove):
	for u in tree[v]:
		if u not in visited and [v, u] != remove and ([u, v] != remove):
			visited.add(u)
			dfs(u, remove)
(n, m) = map(int, input().split())
tree = [[] for _ in range(n)]
k = []
for _ in range(m):
	(a, b) = map(int, input().split())
	tree[a - 1].append(b - 1)
	tree[b - 1].append(a - 1)
	k.append([a - 1, b - 1])
res = 0
for (a, b) in k:
	visited = set()
	dfs(0, [a, b])
	if len(visited) < n:
		res += 1
print(res)


def root(i):
	if par[i] < 0:
		return i
	else:
		return root(par[i])

def size(a):
	return -par[root(a)]

def union(a, b):
	a = root(a)
	b = root(b)
	if a == b:
		return False
	if size(a) < size(b):
		(a, b) = (b, a)
	par[a] += par[b]
	par[b] = a
	return True
(n, m) = map(int, input().split())
bridge = []
for i in range(m):
	bridge.append([int(j) - 1 for j in input().split()])
ans = 0
for i in range(m):
	par = [-1 for _ in range(n)]
	for j in range(m):
		if j != i:
			union(bridge[j][0], bridge[j][1])
	cnt = [i for i in par if i < 0]
	if len(cnt) > 1:
		ans += 1
print(ans)


from collections import defaultdict
from collections import deque
(N, M) = map(int, input().split())
D = defaultdict(list)
Edge = []
for i in range(M):
	(A, B) = map(int, input().split())
	D[A - 1].append(B - 1)
	D[B - 1].append(A - 1)
	Edge.append((A - 1, B - 1))

def dfs(n, vstd, i):
	vstd.add(n)
	for a in D[n]:
		if a not in vstd and (a, n) != i and ((n, a) != i):
			dfs(a, vstd, i)
	return len(vstd)
cnt = 0
for i in Edge:
	if dfs(0, set(), i) < N:
		cnt += 1
print(cnt)


def dfs(cur):
	visited[cur] = 1
	for nx in range(n):
		if G[cur][nx] == 0:
			continue
		if visited[nx]:
			continue
		dfs(nx)
(n, m) = map(int, input().split())
G = [[0] * n for _ in range(n)]
ab = []
for i in range(m):
	(a, b) = map(int, input().split())
	ab.append((a - 1, b - 1))
	G[a - 1][b - 1] = G[b - 1][a - 1] = 1
ans = 0
for (a, b) in ab:
	G[a][b] = G[b][a] = 0
	visited = [0] * n
	dfs(0)
	if not all(visited):
		ans += 1
	G[a][b] = G[b][a] = 1
print(ans)


(n, m) = [int(val) for val in input().split()]
matrix = [[int(val) for val in input().split()] for val in range(m)]
ee = [[val[0] - 1, val[1] - 1] for val in matrix]
cnt = 0
k = 0
for L in range(m):
	xx = [i for i in range(n)]
	for j in range(m):
		if j != k:
			val1 = xx[ee[j][1]]
			val2 = xx[ee[j][0]]
			for i in range(len(xx)):
				if xx[i] == val1:
					xx[i] = val2
	if len(set(xx)) > 1:
		cnt += 1
	k += 1
print(cnt)


from collections import deque
(N, M) = map(int, input().split())
ab = [tuple(map(int, input().split())) for _ in range(M)]
ans = 0
for i in range(M):
	tab = ab[:]
	tab.pop(i)
	r = [[] for _ in range(N)]
	for (a, b) in tab:
		r[a - 1].append(b - 1)
		r[b - 1].append(a - 1)
	l = [True] * N
	l[0] = False
	q = deque(r[0])
	while q:
		t = q.popleft()
		if l[t]:
			l[t] = False
			for j in r[t]:
				if r[j]:
					q.append(j)
	ans += any(l)
print(ans)


(N, M) = map(int, input().split())
AB = [list(map(int, input().split())) for _ in range(M)]
ren = [[] for _ in range(N)]
for (a, b) in AB:
	ren[a - 1].append(b)
	ren[b - 1].append(a)

def dfs(p):
	seen.append(p)
	for i in ren[p - 1]:
		if i not in seen:
			dfs(i)
ans = 0
for (a, b) in AB:
	seen = []
	ren[a - 1].remove(b)
	ren[b - 1].remove(a)
	dfs(a)
	ren[a - 1].append(b)
	ren[b - 1].append(a)
	if len(seen) < N:
		ans += 1
print(ans)


import sys
sys.setrecursionlimit(10 ** 9)

def int1(x):
	return int(x) - 1

def II():
	return int(input())

def MI():
	return list(map(int, input().split()))

def MI1():
	return list(map(int1, input().split()))

def LI():
	return list(map(int, input().split()))

def LI1():
	return list(map(int1, input().split()))

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def MS():
	return input().split()

def LS():
	return list(input())

def LLS(rows_number):
	return [LS() for _ in range(rows_number)]

def printlist(lst, k=' '):
	print(k.join(list(map(str, lst))))
INF = float('inf')
from collections import deque, defaultdict

def solve():
	(N, M) = MI()
	V = [[] for _ in range(N)]
	E = []
	for i in range(M):
		(a, b) = MI1()
		V[a].append(b)
		V[b].append(a)
		E.append((a, b))
	ans = 0
	for (a, b) in E:
		used = [0] * N
		flag = True
		q = deque([a])
		used[a] = 1
		while q:
			cur = q.popleft()
			for nv in V[cur]:
				if (a, b) == (cur, nv) or (a, b) == (nv, cur):
					continue
				if used[nv]:
					continue
				if nv == b:
					flag = False
					q = []
					break
				q.append(nv)
				used[nv] = 1
		if flag:
			ans += 1
	print(ans)

def __starting_point():
	solve()
__starting_point()


def dfs(i, edge):
	if vis[i] == True:
		return
	vis[i] = True
	for j in edge[i]:
		dfs(j, edge)
(N, M) = map(int, input().split())
ab = [[0, 0] for _ in range(M)]
for i in range(M):
	(a, b) = map(int, input().split())
	(ab[i][0], ab[i][1]) = (a, b)
ans = 0
for i in range(M):
	edge = [[] for _ in range(N + 1)]
	for j in range(M):
		if j != i:
			edge[ab[j][0]].append(ab[j][1])
			edge[ab[j][1]].append(ab[j][0])
	vis = [False] * (N + 1)
	vis[0] = True
	dfs(1, edge)
	if False in vis:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
list_AB = [list(map(int, input().split(' '))) for _ in range(m)]
ans = 0
for i in range(m):
	route = [[] for _ in range(n)]
	for j in range(m):
		if j != i:
			(a, b) = (list_AB[j][0], list_AB[j][1])
			route[a - 1].append(b - 1)
			route[b - 1].append(a - 1)
	q = [0]
	l = {0}
	while q:
		x = q.pop(0)
		for p in route[x]:
			if p not in l:
				l.add(p)
				q.append(p)
	if len(list(l)) != n:
		ans += 1
print(ans)


from networkx import *
(n, m) = map(int, input().split())
a = [list(map(int, input().split())) for _ in range(m)]
g = Graph(a)
ans = 0
for x in a:
	g.remove_edges_from([x])
	if not is_connected(g):
		ans += 1
	g.add_edges_from([x])
print(ans)