AtCoder Beginner Contest 075 - Bridge

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.

Source: atcoder | Difficulty: EASY


Solutions:
def root(uf, i):
	if uf[i] == i:
		return i
	else:
		uf[i] = root(uf, uf[i])
		return uf[i]
(n, m) = map(int, input().split())
edge = [list(map(int, input().split())) for _ in range(m)]
ctr = 0
for i in edge:
	uf = [i for i in range(n + 1)]
	for j in edge:
		if i == j:
			continue
		x = root(uf, j[0])
		y = root(uf, j[1])
		uf[x] = y
	for j in range(1, n + 1):
		root(uf, j)
	for j in range(1, n):
		if uf[j] != uf[j + 1]:
			break
	else:
		ctr += 1
print(m - ctr)


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)


class UnionFind:

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

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

	def unite(self, x, y):
		x = self.findRoot(x)
		y = self.findRoot(y)
		if x == y:
			return
		elif self.rnk[x] > self.rnk[y]:
			self.root[y] = x
		else:
			self.root[x] = y
			if self.rnk[x] == self.rnk[y]:
				self.rnk[y] += 1

	def isSame(self, x, y):
		return self.findRoot(x) == self.findRoot(y)
(N, M) = map(int, input().split())
edge = [tuple(map(int, input().split())) for _ in range(M)]
cnt = 0
for i in range(M):
	uf = UnionFind(N + 1)
	for j in range(M):
		if j != i:
			uf.unite(edge[j][0], edge[j][1])
	if not uf.isSame(edge[i][0], edge[i][1]):
		cnt += 1
print(cnt)


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)


def Con(V, E):
	(C1, C2) = (set(), set())
	C1.add(1)
	while len(C1) > len(C2):
		for v in V:
			if v in C1 and v not in C2:
				for e in E:
					if e[0] == v:
						C1.add(e[1])
					elif e[1] == v:
						C1.add(e[0])
				C2.add(v)
	if len(C1) == len(V):
		return True
	else:
		return False
(n, m) = map(int, input().split())
V = [int(i) for i in range(1, n + 1)]
E = []
for i in range(m):
	(s, g) = map(int, input().split())
	E.append([s, g])
ans = 0
for i in range(m):
	if Con(V, E[:i] + E[i + 1:]) == False:
		ans += 1
print(ans)


(n, m) = map(int, input().split())
links = [set() for i in range(n)]
for i in range(m):
	(a, b) = [int(i) - 1 for i in input().split()]
	links[a].add(b)
	links[b].add(a)
ans = 0
pre = [-1] * n
low = [-1] * n

def dfs(v, p, a):
	global ans
	if pre[v] != -1:
		low[a] = min(low[a], low[v])
		return low[a]
	pre[v] = p
	low[v] = p
	for u in links[v]:
		if u == a:
			continue
		low[v] = min(low[v], dfs(u, p + 1, v))
	if pre[v] == low[v]:
		ans += 1
	return low[v]
dfs(0, 0, None)
print(ans - 1)


(N, M) = map(int, input().split())
AB = [tuple(map(int, input().split())) for _ in range(M)]
ab = {}
for (a, b) in AB:
	if not a in ab:
		ab[a] = [b]
	else:
		ab[a] += [b]
	if not b in ab:
		ab[b] = [a]
	else:
		ab[b] += [a]

def check():
	for i in ab:
		if 1 == len(ab[i]):
			return True
	else:
		return False
c = 0
while check():
	for p in ab:
		if 1 == len(ab[p]):
			c += 1
			ab[ab[p][0]].remove(p)
			del ab[p][0]
print(c)


(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))


from collections import deque, defaultdict
import sys
sys.setrecursionlimit(2 ** 20)

class LowLink:

	def __init__(self, v):
		self.size = len(v) + 1
		self.v = v
		self.pre = [None] * self.size
		self.low = [None] * self.size
		self.articulations = []
		self.bridges = []
		for x in range(self.size):
			if self.pre[x] is None:
				self.cnt = 0
				self.dfs(x, None)

	def dfs(self, x, prev):
		self.pre[x] = self.low[x] = self.cnt
		self.cnt += 1
		is_articulation = False
		n = 0
		for y in self.v[x]:
			if self.pre[y] is None:
				n += 1
				low_y = self.dfs(y, x)
				if low_y < self.low[x]:
					self.low[x] = low_y
				if self.pre[x] <= low_y:
					if self.pre[x]:
						is_articulation = True
					if self.pre[x] < low_y:
						self.bridges.append((min(x, y), max(x, y)))
			elif y != prev and self.pre[y] < self.low[x]:
				self.low[x] = self.pre[y]
		if prev is None and n > 1:
			is_articulation = True
		if is_articulation:
			self.articulations.append(x)
		return self.low[x]

def solve():
	(V, E) = map(int, input().split())
	G = defaultdict(lambda : [])
	for _ in range(E):
		(s, t) = map(int, input().split())
		G[s].append(t)
		G[t].append(s)
	lowlink = LowLink(G)
	bridges = lowlink.bridges
	print(len(bridges))

def __starting_point():
	solve()
__starting_point()


from collections import deque

def isBridge(start, goal):
	visited = [False] * N
	q = deque()
	q.append(start)
	visited[start] = True
	while q:
		cur = q.popleft()
		if cur == goal:
			return False
		for nex in adj[cur]:
			if not visited[nex]:
				visited[nex] = True
				q.append(nex)
	return True
(N, M) = map(int, input().split())
adj = list()
for i in range(N):
	adj.append(list())
E = list()
for i in range(M):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	E.append((a, b))
	adj[a].append(b)
	adj[b].append(a)
ans = 0
for e in E:
	(a, b) = e
	adj[a].remove(b)
	adj[b].remove(a)
	if isBridge(a, b):
		ans += 1
	adj[a].append(b)
	adj[b].append(a)
print(ans)


(n, m) = list(map(int, input().split()))
edges = [[] for _ in range(n)]
for i in range(m):
	(a, b) = list(map(int, input().split()))
	edges[a - 1].append(b - 1)
	edges[b - 1].append(a - 1)
ind = 1
queue = [0]
visitedOrder = {}
visited = {}
cnt = 0
while queue:
	cur = queue[-1]
	if cur not in visited:
		visited[cur] = ind
		visitedOrder[cur] = ind
		ind += 1
	neighbours = False
	for nei in edges[cur]:
		if nei not in visited:
			neighbours = True
			queue.append(nei)
			break
	if not neighbours:
		queue.pop()
		if cur != 0:
			connected = visited[cur]
			for nei in edges[cur]:
				if nei != queue[-1]:
					connected = min(connected, visited[nei])
			visited[cur] = connected
			if connected > visitedOrder[queue[-1]]:
				cnt += 1
print(cnt)


(n, m) = map(int, input().split())
E = [[*map(lambda x: int(x) - 1, input().split())] for _ in range(m)]
V = [[] for _ in range(n)]
for (a, b) in E:
	V[a].append(b)
	V[b].append(a)

def dfs(a, b, f):
	if vis[f] == 1:
		return
	vis[f] = 1
	for t in V[f]:
		if f == a and t == b:
			continue
		dfs(a, b, t)
ans = 0
for (a, b) in E:
	vis = [0] * n
	dfs(a, b, a)
	if vis[b] == 0:
		ans += 1
print(ans)


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

def lowlink(g, root=0):
	n = len(g)
	order = [n] * n
	low = [n] * n
	s = [root]
	cnt = 0
	par = [-1] * n
	seq = []
	while s:
		v = s.pop()
		if order[v] != n:
			continue
		order[v] = cnt
		seq.append(v)
		low[v] = cnt
		cnt += 1
		for u in g[v]:
			if order[u] < cnt:
				if par[v] != u:
					low[v] = min(low[v], order[u])
					continue
			else:
				par[u] = v
				s.append(u)
	child = [[] for _ in range(n)]
	for v in range(n):
		if par[v] != -1:
			child[par[v]].append(v)
	seq.reverse()
	for v in seq:
		for u in child[v]:
			low[v] = min(low[v], low[u])
	bridge = []
	for p in range(n):
		for c in child[p]:
			if order[p] < low[c]:
				bridge.append((p, c))
	AP = []
	for v in range(n):
		if v == root:
			if len(child[v]) >= 2:
				AP.append(v)
		else:
			for c in child[v]:
				if order[v] <= low[c]:
					AP.append(v)
					break
	return (AP, bridge)
(_, bridge) = lowlink(g, 0)
print(len(bridge))


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


def main():
	(n, m, *ab) = map(int, open(0).read().split())
	e = [[] for _ in range(n)]
	for (u, v) in zip(*[iter(ab)] * 2):
		e[u - 1].append(v - 1)
		e[v - 1].append(u - 1)
	ans = 0
	for _ in range(m):
		count = 0
		for (i, x) in enumerate(e):
			if len(x) == 1:
				e[i] = []
				e[x[0]].remove(i)
				count += 1
		if count:
			ans += count
		else:
			break
	print(ans)
main()


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)


def search_leaf(edge: list):
	for v in range(N):
		if len(edge[v]) == 1:
			return v
	return -1
(N, M) = map(int, input().split())
edge = [[] for _ in range(N)]
for _ in range(M):
	(a, b) = map(int, input().split())
	edge[a - 1].append(b - 1)
	edge[b - 1].append(a - 1)
ans = 0
for _ in range(M):
	V = search_leaf(edge)
	if V == -1:
		break
	main_land = edge[V][0]
	edge[main_land].remove(V)
	edge[V] = []
	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')

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)


import itertools
(N, M) = list(map(int, input().split()))
ABs = [list(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 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
	size[y] = size[x] + size[y]
	size[x] = 0
loop_list = list(itertools.combinations(ABs, M - 1))
ans = 0
for loop in loop_list:
	par = [i for i in range(N + 1)]
	size = [1 for _ in range(N + 1)]
	for bridge in loop:
		unite(bridge[0], bridge[1])
	if max(size) != N:
		ans += 1
print(ans)


def find(x):
	if par[x] < 0:
		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 False
	else:
		if par[x] > par[y]:
			(x, y) = (y, x)
		par[x] += par[y]
		par[y] = x
		return True

def group_count():
	return sum((x < 0 for x in par))
(n, m) = map(int, input().split())
l = []
for _ in range(m):
	l.append(tuple(map(int, input().split())))
ans = 0
for j in range(m):
	par = [-1] * n
	for (i, ab) in enumerate(l):
		if i != j:
			unite(ab[0] - 1, ab[1] - 1)
	if group_count() == 2:
		ans += 1
print(ans)


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

def dfs(s, parent):
	reach[s] = 1
	for i in l[s]:
		if i == parent:
			continue
		if reach[i] == 0:
			dfs(i, s)
		else:
			reach[i] += 1
loop = [0] * (n + 1)
for i in range(1, n + 1):
	reach = [0] * (n + 1)
	dfs(i, 0)
	if reach[i] != 1:
		loop[i] = 1
ans = 0
for i in range(1, n + 1):
	for j in l[i]:
		if loop[i] == 1 and loop[j] == 1:
			ans += 1
print(m - ans // 2)


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)


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

def dfs(u, seen, e):
	seen[u] = True
	for v in G[u]:
		if seen[v] == True:
			continue
		if [u, v] == e or [v, u] == e:
			continue
		dfs(v, seen, e)
ans = 0
for e in edges:
	seen = [False] * N
	dfs(e[0], seen, e)
	if seen[e[1]] == False:
		ans += 1
print(ans)


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

def des(c, res):
	for i in range(1, n + 1):
		if len(c[i]) == 1:
			c[c[i][0]].remove(i)
			c[i] = []
			res = des(c, res + 1)
	return res
print(des(c, 0))


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)


(N, M) = map(int, input().split())
edges = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	edges[a - 1] += [b - 1]
	edges[b - 1] += [a - 1]
low = [-1] * N
pre = [-1] * N

def dfs(u, count, p):
	pre[u] = count
	low[u] = pre[u]
	for v in edges[u]:
		if pre[v] == -1:
			low[u] = min(low[u], dfs(v, count + 1, u))
		else:
			if v == p:
				continue
			low[u] = min(low[u], low[v])
	return low[u]
count = 0
dfs(0, count, -1)
res = 0
for i in range(1, N):
	res += 1 if low[i] == pre[i] else 0
print(res)


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())
point = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	if b not in point[a - 1]:
		point[a - 1].append(b)
	if a not in point[b - 1]:
		point[b - 1].append(a)
ans = 0
while True:
	(idx, flg) = (0, 0)
	for i in point:
		if len(i) == 1:
			flg = 1
			point[i[0] - 1].remove(idx + 1)
			point[idx] = []
			ans += 1
		idx += 1
	if flg == 0:
		break
print(ans)


(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)


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

def size0find():
	global x, n
	next = []
	for i in range(n):
		if len(x[i]) == 1:
			next.append(i)
			k = x[i][0]
			x[i].remove(k)
			x[k].remove(i)
	return next
cnt = 0
while True:
	y = size0find()
	l = len(y)
	if l == 0:
		break
	cnt += l
print(cnt)


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)


(a, b) = [int(i) for i in input().split()]
n = [[] for i in range(a)]
e = []
for i in range(b):
	(x0, y0) = [int(i) for i in input().split()]
	x = x0 - 1
	y = y0 - 1
	e.append([x, y])
	n[x].append(y)
	n[y].append(x)

def loopn(j, x, y):
	s.append(j)
	for k in n[j]:
		if k not in s and (not (j == x and k == y)) and (not (j == y and k == x)):
			loopn(k, x, y)
x = 0
for (i, j) in e:
	s = []
	loopn(j, i, j)
	if i not in s:
		x += 1
print(x)


(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())
l = [[] for _ in range(n)]
for _ in range(m):
	(a, b) = map(int, input().split())
	l[a - 1].append(b - 1)
	l[b - 1].append(a - 1)
a = 0
while 1:
	x = 0
	for i in range(n):
		if len(l[i]) == 1:
			l[l[i][0]].remove(i)
			l[i] = []
			x += 1
	if x == 0:
		break
	a += x
print(a)


(n, m) = map(int, input().split())
x = [[] for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	if b not in x[a - 1]:
		x[a - 1].append(b)
		if a not in x[b - 1]:
			x[b - 1].append(a)
ans = 0
while True:
	(idx, flg) = (0, 0)
	for i in x:
		if len(i) == 1:
			flg = 1
			x[i[0] - 1].remove(idx + 1)
			x[idx] = []
			ans += 1
		idx += 1
	if flg == 0:
		break
print(ans)


(N, M) = map(int, input().split())
edges = []
graph = [[] for _ in range(N + 1)]
for _ in range(M):
	(a, b) = map(int, input().split())
	edges.append([a, b])
	graph[a].append(b)
	graph[b].append(a)
ans = 0
for i in range(M):
	visited = [0] * (N + 1)
	p = [edges[i][0]]
	visited[p[0]] = 1
	p.extend(graph[edges[i][0]])
	p.remove(edges[i][1])
	for k in p:
		if visited[k]:
			continue
		visited[k] = 1
		p.extend(graph[k])
	if visited[edges[i][1]] == 0:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
graph = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	(a, b) = (a - 1, b - 1)
	graph[a].append(b)
	graph[b].append(a)

def dfs(x, g):
	if vis[x]:
		return
	vis[x] = 1
	for i in g[x]:
		dfs(i, g)
	return
ans = 0
for i in range(len(graph)):
	for j in range(len(graph[i])):
		t = graph[i]
		gn = graph[0:i] + [t[0:j] + t[j + 1:]] + graph[i + 1:]
		vis = [0] * N
		dfs(0, gn)
		if not all(vis):
			ans += 1
print(ans)


(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)


import copy
(N, M) = [int(s) for s in input().split()]
TO = [set() for _ in range(N)]
Edges = [[int(s) for s in input().split()] for _ in range(M)]
for [a, b] in Edges:
	TO[a - 1].add(b - 1)
	TO[b - 1].add(a - 1)
ans = 0
for [a, b] in Edges:
	to = copy.deepcopy(TO)
	to[a - 1].remove(b - 1)
	reach = {a - 1}
	while reach:
		k = reach.pop()
		if k == b - 1:
			break
		while to[k]:
			m = to[k].pop()
			reach.add(m)
	else:
		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)


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

def dfs(cur, a, b):
	if visited[cur] == 1:
		return None
	visited[cur] = 1
	for v in edges[cur]:
		if v != b or cur != a:
			dfs(v, a, b)
ans = 0
for i in l:
	(i, j) = (i[0], i[1])
	visited = [0 for i in range(n)]
	dfs(i, i, j)
	if visited[j] == 0:
		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 node:

	def __init__(self, id):
		self.id = id
		self.root = self

	def findRoot(self):
		if self == self.root:
			return self
		else:
			self.root = self.root.findRoot()
			return self.root

	def resetRoot(self):
		self.root = self

class Tree:

	def __init__(self, num):
		self.nodes = {i: node(i) for i in range(num)}

	def union(self, one, other):
		root1 = one.findRoot()
		root2 = other.findRoot()
		root1.root = root2.root = self.nodes[min(root1.id, root2.id)]

	def resetTree(self):
		for n in self.nodes.values():
			n.resetRoot()

	def makeTree(self, Edge):
		self.edge = Edge
		for (x, y) in Edge:
			self.union(self.nodes[x - 1], self.nodes[y - 1])

def main():
	with open(0) as f:
		(N, M) = map(int, f.readline().split())
		Edge = [tuple(map(int, line.split())) for line in f.readlines()]
	tree = Tree(N)
	ans = 0
	for i in range(M):
		edge = [v for v in Edge if v != Edge[i]]
		tree.makeTree(edge)
		if any((x.findRoot().id != 0 for x in tree.nodes.values())):
			ans += 1
		tree.resetTree()
	print(ans)

def __starting_point():
	main()
__starting_point()


from collections import defaultdict

def dfs(x):
	if f[x] == 1:
		return
	f[x] = 1
	for nex in dd[x]:
		if x == a and nex == b:
			continue
		dfs(nex)
(n, m) = map(int, input().split())
dd = defaultdict(list)
lst = []
ans = 0
for i in range(m):
	(a, b) = map(int, input().split())
	lst.append((a, b))
	dd[a].append(b)
	dd[b].append(a)
for (a, b) in lst:
	f = [0] * (n + 1)
	dfs(a)
	if f[b] != 1:
		ans += 1
print(ans)


(N, M) = map(int, input().split())
edges = [[] for _ in range(N)]
ans = 0
for _ in range(M):
	(a, b) = map(lambda n: int(n) - 1, input().split())
	edges[a].append(b)
	edges[b].append(a)
changed = True
sumi = []
count = 0
while changed:
	changed = False
	for i in range(len(edges)):
		if len(edges[i]) == 1 and i not in sumi:
			edges[edges[i][0]].remove(i)
			sumi.append(i)
			changed = True
			count += 1
print(count)


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 = [tuple(map(int, input().split())) for _ in range(M)]
T = [[] for _ in range(N)]
for (a, b) in AB:
	a -= 1
	b -= 1
	T[a].append(b)
	T[b].append(a)
ans = M
for (a, b) in AB:
	a -= 1
	b -= 1
	T[a].remove(b)
	T[b].remove(a)
	visited = [False] * N

	def rec(x):
		visited[x] = True
		for y in T[x]:
			if not visited[y]:
				rec(y)
	rec(0)
	ans -= all(visited)
	T[a].append(b)
	T[b].append(a)
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)


import copy
(n, m) = map(int, input().split())
temp = [[] for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	a = a - 1
	b = b - 1
	temp[a].append(b)
	temp[b].append(a)
count = 0
a = []
c = True
while c:
	c = False
	for i in range(n):
		if len(temp[i]) == 1 and i not in a:
			temp[temp[i][0]].remove(i)
			a.append(i)
			count = count + 1
			c = True
print(count)


(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)


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) = map(int, input().split())
l = []
for i in range(m):
	l.append(list(map(int, input().split())))
ans = 0
for i in range(m):
	a = UnionFind(n)
	for j in range(m):
		if i == j:
			continue
		a.union(l[j][0] - 1, l[j][1] - 1)
	if a.group_count() == 2:
		ans += 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())
a = []
b = []
g = [[] for i in range(n)]
for i in range(m):
	(ai, bi) = map(int, input().split())
	ai -= 1
	bi -= 1
	g[ai].append(bi)
	g[bi].append(ai)
	a.append(ai)
	b.append(bi)
used = [False for i in range(n)]
dame1 = 0
dame2 = 0

def dfs(x):
	used[x] = True
	for y in g[x]:
		if dame1 == x and dame2 == y:
			continue
		if not used[y]:
			dfs(y)
ans = 0
for i in range(m):
	used = [False for i in range(n)]
	dame1 = a[i]
	dame2 = b[i]
	dfs(a[i])
	if not used[b[i]]:
		ans += 1
print(ans)


f = lambda : map(int, input().split())
(n, m) = f()
d = [[] for _ in range(n + 1)]
c = []
for _ in range(m):
	(a, b) = f()
	d[a] += [b]
	d[b] += [a]
	c += [[a, b]]
ans = 0
for (i, j) in c:
	a = [0] * (n + 1)
	b = list(d[i])
	b.remove(j)
	now = 0
	while b:
		now = b.pop(0)
		if a[now] == 0:
			a[now] += 1
			for k in d[now]:
				if a[k] == 0 and k != i:
					b += [k]
	if a[j] == 0:
		ans += 1
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)


import sys
(n, m, *ab) = map(int, sys.stdin.read().split())
graph = [set() for _ in range(n)]
for (a, b) in zip(*[iter(ab)] * 2):
	a -= 1
	b -= 1
	graph[a].add(b)
	graph[b].add(a)

def main():
	stack = [i for i in range(n) if len(graph[i]) == 1]
	bridges = 0
	while stack:
		x = stack.pop()
		if not graph[x]:
			continue
		y = graph[x].pop()
		graph[y].remove(x)
		bridges += 1
		if len(graph[y]) == 1:
			stack.append(y)
	print(bridges)
main()


from collections import deque
(n, m) = map(int, input().split())
graph = [[] for _ in range(n)]
deg = [0] * n
seen = [False] * n
for i in range(m):
	(x, y) = map(int, input().split())
	graph[x - 1] += [y - 1]
	graph[y - 1] += [x - 1]
	deg[x - 1] += 1
	deg[y - 1] += 1
q = deque([i for i in range(n) if deg[i] == 1])
while q:
	v = q.popleft()
	seen[v] = True
	for i in graph[v]:
		deg[i] -= 1
		if deg[i] == 1:
			q.append(i)
if all((seen[i] == 1 for i in range(n))):
	print(n - 1)
	exit()
print(seen.count(1))


def main():
	(n, m, *ab) = map(int, open(0).read().split())
	e = [set() for _ in range(n)]
	for (u, v) in zip(*[iter(ab)] * 2):
		e[u - 1].add(v - 1)
		e[v - 1].add(u - 1)
	ans = 0
	for _ in range(m):
		count = 0
		for (i, x) in enumerate(e):
			if len(x) == 1:
				j = x.pop()
				e[j] -= {i}
				count += 1
		if count:
			ans += count
		else:
			print(ans)
			exit()
main()


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())
g = [[] for i in range(1 + n)]
v = [0] * (1 + n)
e = []
for i in range(m):
	(a, b) = map(int, input().split())
	e.append((a, b))
	g[a].append(b)
	g[b].append(a)

def dfs(st, ed):
	q = []
	q.append(st)
	while q:
		cur = q.pop()
		v[cur] = 1
		if cur == ed:
			return True
		for nb in g[cur]:
			if v[nb] != 1 and (cur, nb) != (st, ed):
				q.append(nb)
	return False
ans = 0
for (a, b) in e:
	v = [0] * (1 + n)
	if not dfs(a, b):
		ans += 1
print(ans)


(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)


(N, M) = map(int, input().split())
v = list(range(1, N + 1))
edges = [[] for _ in range(N + 1)]
for _ in range(M):
	(a, b) = map(int, input().split())
	edges[a] += [b]
	edges[b] += [a]

def dfs(v, e):
	for x in v:
		if len(e[x]) == 1:
			t = e[x][0]
			e[x] = []
			e[t].remove(x)
			v.remove(x)
			return dfs(v, e) + 1
	return 0
print(dfs(v, edges))


import sys
input = sys.stdin.readline
(N, M) = [int(x) for x in input().split()]
G = [[] for _ in range(N + 1)]
for _ in range(M):
	(a, b) = [int(x) for x in input().split()]
	G[a].append(b)
	G[b].append(a)
ans = 0
for _ in range(M):
	for i in range(1, N + 1):
		if len(G[i]) == 1:
			tmp = G[i][0]
			G[i].remove(tmp)
			G[tmp].remove(i)
			ans += 1
print(ans)


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 unite(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)
(N, M) = map(int, input().split())
A = [0] * M
t = 0
B = [0] * M
for i in range(M):
	(a, b) = map(int, input().split())
	A[i] = [a - 1, b - 1]
for t in range(M):
	UF = UnionFind(N)
	for i in range(M):
		if i != t:
			UF.unite(A[i][0], A[i][1])
	if UF.same(A[t][0], A[t][1]) == False:
		B[t] = 1
print(sum(B))


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())
paths = []
graph = {}
for n in range(1, N + 1):
	graph[n] = set()
for m in range(M):
	(a, b) = map(int, input().split())
	paths.append((a, b))
	graph[a].add(b)
	graph[b].add(a)
ans = 0
for m in range(M):
	(a, b) = paths[m]
	graph[a].remove(b)
	graph[b].remove(a)
	land = {1}
	connected = {1} | graph[1]
	while land != connected:
		land = connected.copy()
		for n in land:
			connected |= graph[n]
	if len(land) != N:
		ans += 1
	graph[a].add(b)
	graph[b].add(a)
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)]
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()


(n, m) = map(int, input().split())
adj = [list() for _ in range(n)]
for _ in range(m):
	(a, b) = map(int, input().split())
	adj[a - 1].append(b - 1)
	adj[b - 1].append(a - 1)
loop = True
bridge = 0
while loop:
	loop = False
	for (i, ai) in enumerate(adj):
		if len(ai) == 1:
			adj[i] = []
			adj[ai[0]].remove(i)
			bridge += 1
			loop = True
print(bridge)


def f(L, res):
	for i in range(1, N + 1):
		if len(L[i]) == 1:
			L[L[i][0]].remove(i)
			L[i] = []
			res = f(L, res + 1)
	return res
(N, M) = map(int, input().split())
L = [[] for _ in range(N + 1)]
for i in range(M):
	(a, b) = map(int, input().split())
	L[a].append(b)
	L[b].append(a)
print(f(L, 0))


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) = (int(x) for x in input().split())
edge = [tuple((int(x) for x in input().split())) for _ in range(M)]
import numpy as np
from scipy.sparse.csgraph import floyd_warshall
INF = 100
tmpl_graph = [[INF if i != j else 0 for j in range(N)] for i in range(N)]
ans = 0
for E in edge:
	edgeWithoutE = edge.copy()
	edgeWithoutE.remove(E)
	graph = np.array(tmpl_graph)
	for x in edgeWithoutE:
		graph[x[0] - 1, x[1] - 1] = 1
		graph[x[1] - 1, x[0] - 1] = 1
	graph = floyd_warshall(graph, directed=False)
	if len(graph[graph == 100]) > 0:
		ans += 1
print(ans)


(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())
L = [[] for i in range(N)]

def dfs(bef, hr, g, vst):
	vst.add(hr)
	if hr == g:
		return 1
	cnt = 0
	for nxt in L[hr]:
		if nxt == bef or nxt in vst:
			continue
		cnt += dfs(hr, nxt, g, vst)
	return cnt
ab = [list(map(lambda x: int(x) - 1, input().split())) for i in range(M)]
for (a, b) in ab:
	L[a].append(b)
	L[b].append(a)
print(sum((dfs(b, a, b, set()) == 0 for (a, b) in ab)))


(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(' '))
a = [list(map(int, input().split(' '))) for i in range(m)]
a_connects = [[] for i in range(n)]
for (x, y) in a:
	a_connects[x - 1].append(y - 1)
	a_connects[y - 1].append(x - 1)
a_connect_sums = [len(connect) for connect in a_connects]
bridge_count = 0
while 1 in a_connect_sums:
	x = a_connect_sums.index(1)
	y = a_connects[x][0]
	a_connects[x].remove(y)
	a_connects[y].remove(x)
	a_connect_sums[x] -= 1
	a_connect_sums[y] -= 1
	bridge_count += 1
print(bridge_count)


(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)


import sys
read = sys.stdin.read
(n, m) = map(int, input().split())
edge = [tuple(map(int, lst.split())) for lst in read().splitlines()]

def isconn(v, e0):
	clst = [1] * (n + 1)
	clst[v] = 0
	for _ in range(n):
		for e in edge:
			if e != e0:
				tmp = clst[e[1]] & clst[e[0]]
				clst[e[1]] = tmp
				clst[e[0]] = tmp
	if sum(clst) > 1:
		return False
	else:
		return True
ans = 0
for e in edge:
	if not isconn(1, e):
		ans += 1
print(ans)


(N, M) = map(int, input().split())
v = [i for i in range(1, N + 1)]
e = [[]] * (N + 1)
for i in range(M):
	(a, b) = map(int, input().split())
	e[a] = e[a] + [b]
	e[b] = e[b] + [a]

def dfs(v, e):
	for num in v:
		if len(e[num]) == 1:
			tmp_num = e[num][0]
			v.remove(num)
			e[num] = []
			e[tmp_num].remove(num)
			return dfs(v, e) + 1
	return 0
print(dfs(v, e))


(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)


import networkx as nx
(N, M) = map(int, input().split())
G = nx.Graph()
G.add_nodes_from(range(1, N + 1))
G.add_edges_from([tuple(map(int, input().split())) for _ in range(M)])
print(len(tuple(nx.bridges(G))))


(n, m) = map(int, input().split())
xs = [tuple(map(int, input().split())) for _ in range(m)]
c = 0

def root(n):
	if union[n] == n:
		return n
	union[n] = root(union[n])
	return union[n]
for i in range(m):
	union = {x: x for x in range(1, n + 1)}
	t = 0
	for j in range(i):
		(x, y) = xs[j]
		union[root(x)] = root(y)
	for j in range(i + 1, m):
		(x, y) = xs[j]
		union[root(x)] = root(y)
	for k in range(1, n + 1):
		if union.get(k) == k:
			t += 1
	if t != 1:
		c += 1
print(c)


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())
G = [[] for _ in range(N + 1)]
for i in range(M):
	(c, d) = map(int, input().split())
	G[c].append(d)
	G[d].append(c)
ans = 0
for i in range(M):
	for j in range(1, N + 1):
		if len(G[j]) == 1:
			tmp = G[j][0]
			G[j].remove(tmp)
			G[tmp].remove(j)
			ans += 1
print(ans)


(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())
T = [[0 for i in range(N + 1)] for j in range(N + 1)]
for i in range(M):
	(a, b) = map(int, input().split())
	T[a][b] = 1
	T[b][a] = 1
ans = 0

def f(v, x, y):
	global N, M, T, a
	a[v] = 1
	for i in range(N + 1):
		if v == x and i == y or (v == y and i == x):
			continue
		elif T[v][i] == 0 or a[i] == 1:
			continue
		f(i, x, y)
for i in range(1, N + 1):
	for j in range(i, N + 1):
		a = [0 for _ in range(N + 1)]
		f(1, i, j)
		if sum(a) != N:
			ans += 1
print(ans)


import sys
from collections import Counter
(n, m, *ab) = (int(x) for x in sys.stdin.read().split())
bridges = 0
still_exist = True
while still_exist:
	bef = len(ab)
	for (vertex, edges_count) in Counter(ab).items():
		if edges_count == 1:
			i = ab.index(vertex)
			if i % 2 == 0:
				del ab[i:i + 2]
			else:
				del ab[i - 1:i + 1]
			bridges += 1
			break
	aft = len(ab)
	if bef == aft:
		still_exist = False
print(bridges)


(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())
l = [[] for i in range(n)]
o = []
ans = 0
for i in range(m):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	l[a].append(b)
	l[b].append(a)
	o.append([a, b])

def dfs(f):
	if vis[f] == 1:
		return
	vis[f] = 1
	for t in l[f]:
		if f != a or t != b:
			dfs(t)
for (a, b) in o:
	vis = [0] * n
	dfs(a)
	if vis[b] == 0:
		ans += 1
print(ans)


(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)


import queue
(n, m) = list(map(int, input().split()))
am_bm = []
side_map = dict()
for i in range(m):
	(ai, bi) = list(map(int, input().split()))
	if ai not in side_map:
		side_map[ai] = set()
		side_map[ai].add(bi)
	else:
		side_map[ai].add(bi)
	if bi not in side_map:
		side_map[bi] = set()
		side_map[bi].add(ai)
	else:
		side_map[bi].add(ai)
	am_bm.append((ai, bi))
counter = 0
for i in range(m):
	(a, b) = am_bm[i]
	q = queue.Queue()
	q.put(1)
	node_passed = set()
	node_passed.add(1)
	while not q.empty():
		a_tmp = q.get()
		for b_tmp in side_map[a_tmp]:
			if a_tmp == a and b_tmp == b or (a_tmp == b and b_tmp == a):
				pass
			elif b_tmp not in node_passed:
				q.put(b_tmp)
				node_passed.add(b_tmp)
	if len(node_passed) == n:
		counter += 1
print(m - counter)


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

def bfs(n, t, v):
	for p in t[n]:
		if p not in visited:
			visited.add(p)
			bfs(p, t, v)
ans = 0
for i in range(M):
	t = {i: [] for i in range(1, N + 1)}
	visited = set()
	for j in range(M):
		if i == j:
			continue
		(a, b) = ab[j]
		t[a].append(b)
		t[b].append(a)
	bfs(1, t, visited)
	if len(visited) != N:
		ans += 1
print(ans)


class UnionFind:

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

	def _root(self, x):
		stack = []
		while self._table[x] >= 0:
			stack.append(x)
			x = self._table[x]
		for y in stack:
			self._table[y] = x
		return x

	def unite(self, x, y):
		(x, y) = (self._root(x), self._root(y))
		if x == y:
			return
		if x > y:
			(x, y) = (y, x)
		self._table[x] += self._table[y]
		self._table[y] = x

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

	def count_members(self, x):
		return -self._table[self._root(x)]

	def count_groups(self):
		return len({self._root(i) for i in range(self._n)})

	def __str__(self):
		return str([self._root(i) for i in range(self._n)])

	def __repr__(self):
		return repr([self._root(i) for i in range(self._n)])
(n, m, *AB) = map(int, open(0).read().split())
ans = 0
for i in range(m):
	uf = UnionFind(n)
	for (j, (a, b)) in enumerate(zip(AB[::2], AB[1::2])):
		if i == j:
			continue
		uf.unite(a - 1, b - 1)
	ans += uf.count_groups() != 1
print(ans)


from collections import deque
(n, m) = map(int, input().split())
l = [[] for _ in range(n)]
edge = []
ans = 0
for _ in range(m):
	(a, b) = map(int, input().split())
	l[a - 1].append(b - 1)
	l[b - 1].append(a - 1)
	edge.append([a - 1, b - 1])
for (i, j) in edge:
	q = deque([i])
	visited = [0] * n
	while q:
		x = q.pop()
		if x == j:
			break
		visited[x] = 1
		for k in l[x]:
			if visited[k] == 0 and (not (x == i and k == j)):
				q.append(k)
	else:
		ans += 1
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)


def f(v, e):
	for x in v:
		if len(e[x]) == 1:
			y = e[x][0]
			v.remove(x)
			e[x] = []
			e[y].remove(x)
			return f(v, e) + 1
	return 0
(n, m) = map(int, input().split())
v = list(range(1, n + 1))
e = [[]] * (n + 1)
for _ in [0] * m:
	(x, y) = map(int, input().split())
	e[x] = e[x] + [y]
	e[y] = e[y] + [x]
print(f(v, e))


(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)


(n, m) = map(int, input().split())
ab = [tuple(map(int, input().split())) for _ in range(m)]
graph = {x: [] for x in range(1, n + 1)}
for (x, y) in ab:
	graph[x].append(y)
	graph[y].append(x)

def dfs(v):
	visited.append(v)
	for v2 in graph[v]:
		if v2 not in visited:
			dfs(v2)
res = 0
for (a, b) in ab:
	graph[a].remove(b)
	graph[b].remove(a)
	visited = []
	dfs(1)
	if len(visited) != n:
		res += 1
	graph[a].append(b)
	graph[b].append(a)
print(res)


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)


(n, m) = map(int, input().split())
A = [list(map(int, input().split())) for i in range(m)]
B = [[] for i in range(n + 1)]
for i in range(m):
	B[A[i][0]].append(A[i][1])
	B[A[i][1]].append(A[i][0])
co = 0
ok = 0
while ok == 0:
	ok = 1
	for i in range(1, n + 1):
		if len(B[i]) == 1:
			ok = 0
			k = B[i][0]
			B[i].remove(k)
			B[k].remove(i)
			co += 1
print(co)


(n, m) = map(int, input().split())
a = []
for i in range(m):
	(x, y) = map(int, input().split())
	a.append([x, y])
ans = 0
for i in range(m):
	b = [a[i][0]]
	for j in range(n):
		for k in range(m):
			if k != i and a[k][0] in b:
				b.append(a[k][1])
			elif k != i and a[k][1] in b:
				b.append(a[k][0])
	if a[i][1] not in b:
		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)
print(len(tuple(bridges(g))))


(N, M) = map(int, input().split())
ab = [list(map(int, input().split())) for _ in [0] * M]
g = [set() for _ in [0] * N]
[g[b - 1].add(a - 1) for (a, b) in ab]
[g[a - 1].add(b - 1) for (a, b) in ab]
q = [i for (i, gg) in enumerate(g) if len(gg) == 1]
cnt = 0
while q:
	cnt += len(q)
	for i in q:
		g[i] = set()
		for j in range(N):
			g[j] = g[j] - {i}
	q = [i for (i, gg) in enumerate(g) if len(gg) == 1]
print(min(cnt, M))


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())
s = [set() for i in range(n)]
e = []
for i in range(m):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	s[a].add(b)
	s[b].add(a)
	e.append([a, b])

def dfs(u, v, c):
	visited[u] = 1
	c += 1
	if u == v:
		d.append(c)
		return True
	for i in s[u]:
		if visited[i]:
			continue
		if c == 1:
			if i == v:
				continue
		dfs(i, v, c)
cnt = 0
for i in range(m):
	(x, y) = (e[i][0], e[i][1])
	visited = [0 for i in range(n)]
	d = []
	dfs(x, y, 0)
	if len(d) > 0:
		cnt += 1
print(m - cnt)


class UnionFind:

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

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

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x > y:
			(x, y) = (y, x)
		if x == y:
			return
		else:
			self.para[x] += self.para[y]
			self.para[y] = x

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

	def count(self, x):
		return -self.para[self.find(x)]
(N, M) = map(int, input().split())
un_orginal = UnionFind(N)
A = [tuple(map(int, input().split())) for _ in range(M)]
for (a, b) in A:
	un_orginal.unite(a, b)
ans = 0
for i in range(M):
	un = UnionFind(N)
	for k in range(M):
		if i == k:
			continue
		else:
			un.unite(A[k][0], A[k][1])
	cnt = 0
	for k in range(N + 1):
		if un_orginal.count(k) == un.count(k):
			cnt += 1
	if cnt == N + 1:
		ans += 1
print(M - ans)


(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())
(a, ans) = ([[], []], 0)
for i in range(m):
	(aa, bb) = map(int, input().split())
	a[0].append(aa)
	a[1].append(bb)
flag = True
while flag:
	flag = False
	for i in range(1, n + 1):
		c = 0
		p = []
		for j in range(len(a[0])):
			if a[0][j] == i:
				c += 1
				p.append(j)
			if a[1][j] == i:
				c += 1
				p.append(j)
			if c > 1:
				break
		if c == 1:
			ans += 1
			del a[0][p[0]], a[1][p[0]]
			flag = True
			break
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()


(n, m) = map(int, input().split())
l = list()
for i in range(m):
	l.append(list(map(int, input().split())))
p = 0
for o in range(m):
	d = {i: [] for i in range(1, n + 1)}
	for i in range(m):
		if i == o:
			continue
		(a, b) = l[i]
		d[a].append(b)
		d[b].append(a)
	q = [1]
	s = {i: 1 for i in range(1, n + 1)}
	while len(q) > 0:
		for i in d[q.pop()]:
			if s[i]:
				s[i] = 0
				q.append(i)
	if 1 in s.values():
		p += 1
print(p)


(N, M) = map(int, input().split())
MAP = [[0] * N for i in range(N)]
S = [0] * N
for i in range(M):
	(a, b) = map(int, input().split())
	MAP[a - 1][b - 1] += 1
	MAP[b - 1][a - 1] += 1
	S[a - 1] += 1
	S[b - 1] += 1
c = -1
s = 0
while True:
	c += 1
	if c == N:
		break
	if S[c] == 1:
		for i in range(N):
			if MAP[c][i] == 1:
				MAP[c][i] = 0
				MAP[i][c] = 0
				S[c] -= 1
				S[i] -= 1
				s += 1
				c = -1
				break
print(s)


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 defaultdict
(N, M) = map(int, input().split())
flg = 1
ans = 0
a = [list(map(int, input().split())) for _ in range(M)]
while flg == 1:
	d = defaultdict(int)
	flg = 0
	for link in a:
		d[link[0]] += 1
		d[link[1]] += 1
	for node in range(1, M + 1):
		if d[node] == 1:
			ans += 1
			flg = 1
			a = [x for x in a if node not in x]
print(ans)


(N, M) = map(int, input().split())
R = []
G = {k: [] for k in range(N)}
for _ in range(M):
	(a, b) = map(int, input().split())
	G[a - 1].append(b - 1)
	G[b - 1].append(a - 1)
	R.append((a - 1, b - 1))

def dfs(p, i, arrived):
	for n in G[p]:
		if arrived[n] is False and tuple(sorted((p, n))) != R[i]:
			arrived[n] = True
			dfs(n, i, arrived)
ans = 0
for i in range(M):
	arrived = [False] * N
	arrived[0] = True
	dfs(0, i, arrived)
	if not all(arrived):
		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)


import networkx as nx
(n, m, *AB) = map(int, open(0).read().split())
G = nx.Graph()
G.add_edges_from(zip(AB[::2], AB[1::2]))
print(len(list(nx.bridges(G))))


(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)


import queue
(n, m) = list(map(int, input().split()))
route = [[] for _ in range(n)]
vals = []
for _ in range(m):
	(a, b) = list(map(int, input().split()))
	route[a - 1].append(b - 1)
	route[b - 1].append(a - 1)
	vals.append([a - 1, b - 1])
ans = m
for i in range(m):
	route2 = set()
	q = queue.Queue()
	q.put(0)
	route[vals[i][0]].remove(vals[i][1])
	route[vals[i][1]].remove(vals[i][0])
	while not q.empty():
		a = q.get()
		if not a in route2:
			route2.add(a)
			for j in route[a]:
				q.put(j)
		if len(route2) == n:
			ans -= 1
			break
	route[vals[i][0]].append(vals[i][1])
	route[vals[i][1]].append(vals[i][0])
print(ans)


(N, M) = map(int, input().split())
C = [[] for i in range(N)]
for i in range(M):
	(a, b) = map(int, input().split())
	C[a - 1].append(b - 1)
	C[b - 1].append(a - 1)
cnt = 0
f = True
while f:
	f = False
	for i in range(N):
		if len(C[i]) == 1:
			cnt += 1
			idx = C[C[i][0]].index(i)
			C[C[i][0]].pop(idx)
			C[i].pop()
			f = True
print(cnt)


(N, M) = map(int, input().split())
E = {i: [] for i in range(N)}
mat = [[False for i in range(N)] for j in range(N)]
for _ in range(M):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	E[a].append(b)
	E[b].append(a)
	mat[a][b] = True
	mat[b][a] = True
cnt = 0
for i in range(N):
	if sum(mat[i]) == 1:
		while True:
			if len(E[i]) != 1:
				break
			j = E[i][0]
			E[i].remove(j)
			E[j].remove(i)
			cnt += 1
			i = j
print(cnt)


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)


(N, M) = map(int, input().split())
edge = [set() for i in range(N)]
l = []
for i in range(M):
	(a, b) = map(int, input().split())
	edge[a - 1].add(b - 1)
	edge[b - 1].add(a - 1)
	l.append((a - 1, b - 1))
ans = M
for i in range(M):
	used = [False] * N
	(a, b) = l[i]
	edge[a].discard(b)
	edge[b].discard(a)
	stack = [0]
	while stack:
		prev = stack.pop()
		if used[prev]:
			continue
		used[prev] = True
		for to in edge[prev]:
			stack.append(to)
	if all(used):
		ans -= 1
	edge[a].add(b)
	edge[b].add(a)
print(ans)


import sys
input = sys.stdin.readline

class UnionFind:

	def __init__(self, N):
		self.N = N
		self.__make_set()

	def __make_set(self):
		self._parent = list(range(self.N + 1))
		self._rank = [0] * (self.N + 1)
		self._size = [1] * (self.N + 1)

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

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		x_rank = self._rank[x_root]
		y_rank = self._rank[y_root]
		if x_rank > y_rank:
			self._parent[y_root] = x_root
			self._size[x_root] += self._size[y_root]
		elif x_rank < y_rank:
			self._parent[x_root] = y_root
			self._size[y_root] += self._size[x_root]
		else:
			self._parent[y_root] = x_root
			self._rank[x_root] += 1
			self._size[x_root] += self._size[y_root]

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

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

def main():
	(N, M) = list(map(int, input().split()))
	a = [None] * M
	b = [None] * M
	for i in range(M):
		(a[i], b[i]) = list(map(int, input().split()))
	ans = 0
	for i in range(M):
		uf = UnionFind(N)
		for j in range(M):
			if j == i:
				continue
			uf.union(a[j], b[j])
		if not uf.same_set(a[i], b[i]):
			ans += 1
	print(ans)

def __starting_point():
	main()
__starting_point()


import copy
from collections import deque
(N, M) = map(int, input().split())
lsside = [[] for i in range(N + 1)]
lsline = []
for i in range(M):
	(a, b) = map(int, input().split())
	lsside[a].append(b)
	lsside[b].append(a)
	lsline.append([a, b])
ans = 0
lsloop = []
for i in range(M):
	graph = copy.deepcopy(lsside)
	a = lsline[i][0]
	b = lsline[i][1]
	graph[a].remove(b)
	graph[b].remove(a)
	used = [False for i in range(N + 1)]
	ii = 1
	d = deque()
	d.append(a)
	used[a] = True
	while d:
		v = d.popleft()
		for i in graph[v]:
			if used[i]:
				continue
			ii += 1
			d.append(i)
			used[i] = True
	lsloop.append(ii)
ans = M - lsloop.count(N)
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)


(N, M) = map(int, input().split())
lis = [[] for _ in range(N + 1)]
for _ in range(M):
	(a, b) = map(int, input().split())
	lis[a].append(b)
	lis[b].append(a)
counter = 0
flag = True
while flag:
	flag = False
	for index in range(1, N + 1):
		if len(lis[index]) == 1:
			lis[lis[index][0]].remove(index)
			lis[index].pop(0)
			counter += 1
			flag = True
print(counter)


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)


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

def dfs(now):
	searched[now] = True
	for next in graph[now]:
		if searched[next]:
			continue
		if min(now, next) == a and max(now, next) == b:
			continue
		dfs(next)
ans = M
for i in range(M):
	(a, b) = edge[i]
	searched = [False] * N
	dfs(0)
	if sum(searched) == N:
		ans -= 1
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 copy import deepcopy

def dfs(v):
	visited[v] = 1
	ret = 1
	for w in range(n):
		if [v, w] not in r:
			continue
		elif visited[w] == 1:
			continue
		ret += dfs(w)
		visited[w] = 1
	return ret
(n, m) = map(int, input().split())
x = []
cnt = 0
for _ in range(m):
	(a, b) = map(int, input().split())
	x.append([a - 1, b - 1])
	x.append([b - 1, a - 1])
for i in range(m):
	r = deepcopy(x)
	r.pop(2 * i)
	r.pop(2 * i)
	visited = [0] * n
	if dfs(0) == n:
		cnt += 1
print(m - 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())
T = [input().split() for _ in range(M)]

class U(list):

	def __init__(self, n):
		super().__init__(range(n))

	def f(self, i):
		if i == self[i]:
			return i
		self[i] = self.f(self[i])
		return self[i]

	def u(self, i, j):
		self[self.f(i)] = self.f(j)
c = 0
for i in range(M):
	u = U(N)
	for j in range(M):
		if i != j:
			(p, q) = T[j]
			u.u(int(p) - 1, int(q) - 1)
	for j in range(N):
		u.f(j)
	c += len(set(u)) == 2
print(c)


(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)


def main():
	(n, m) = map(int, input().split())
	e = [set() for _ in range(n)]
	for _ in range(m):
		(u, v) = map(lambda x: int(x) - 1, input().split())
		e[u].add(v)
		e[v].add(u)
	ans = 0
	for _ in range(m):
		count = 0
		for (i, x) in enumerate(e):
			if len(x) == 1:
				j = x.pop()
				e[j] -= {i}
				count += 1
		if count:
			ans += count
		else:
			print(ans)
			exit()
main()


(N, M) = map(int, input().split())
d = [[] for i in range(N)]
for i in range(M):
	(b, c) = map(int, input().split())
	d[b - 1].append(c - 1)
	d[c - 1].append(b - 1)
a = 0
while True:
	count = 0
	for i in range(N):
		if len(d[i]) == 1:
			d[d[i][0]].remove(i)
			d[i] = []
			count += 1
	if count == 0:
		break
	a += count
print(a)


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)


(N, M) = [int(x) for x in input().split()]
AB = [[int(x) for x in input().split()] for _ in range(M)]
cnt = 0
for j in range(M):
	E = {i: [] for i in range(N)}
	for i in range(M):
		if j == i:
			continue
		(a, b) = AB[i]
		E[a - 1].append(b - 1)
		E[b - 1].append(a - 1)
	visited = [0] * N
	stk = [(0, -1)]
	while stk:
		(v, p) = stk.pop()
		if visited[v] == 1:
			continue
		visited[v] = 1
		for i in E[v]:
			if i != p:
				stk.append((i, v))
	if 0 in visited:
		cnt += 1
print(cnt)


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

def dfs(v, ID):
	visited.add(v)
	for (u, idx) in G[v]:
		if idx == ID or u in visited:
			continue
		dfs(u, ID)
for i in range(M):
	visited = set([])
	start = H[i][0]
	goal = H[i][1]
	dfs(start, i)
	if goal not in visited:
		ans += 1
print(ans)


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)


import copy
(N, M) = map(int, input().split())
A = [[] for n in range(N)]
I = []
for m in range(M):
	I.append(list(map(int, input().split())))
	I[m][0] -= 1
	I[m][1] -= 1
	A[I[m][0]].append(I[m][1])
	A[I[m][1]].append(I[m][0])

def check(n):
	global C, AA
	if C[n] == 1:
		return
	else:
		C[n] = 1
		for nn in AA[n]:
			check(nn)
		return
ans = M
for i in I:
	C = [0 for n in range(N)]
	AA = copy.deepcopy(A)
	AA[i[0]].remove(i[1])
	AA[i[1]].remove(i[0])
	check(0)
	ans -= all(C)
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)


class UnionFind:

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

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

	def unite(self, x, y):
		rx = self.find_root(x)
		ry = self.find_root(y)
		if rx == ry:
			return
		if self.rank[rx] < self.rank[ry]:
			self.parent[rx] = ry
		else:
			self.parent[ry] = rx
			if self.rank[rx] == self.rank[ry]:
				self.rank[rx] += 1

	def is_same(self, x, y):
		return self.find_root(x) == self.find_root(y)
(N, M) = map(int, input().split())
edge = []
bridge = 0
for _ in range(M):
	e = list(map(lambda x: int(x) - 1, input().split()))
	edge.append(e)
for i in range(M):
	uf = UnionFind(N)
	for j in range(M):
		if j == i:
			continue
		uf.unite(edge[j][0], edge[j][1])
	if uf.find_root(edge[i][0]) != uf.find_root(edge[i][1]):
		bridge += 1
print(bridge)


(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)


(n, m) = map(int, input().split())
graph = {i: [] for i in range(1, n + 1)}
for _ in range(m):
	(a, b) = map(int, input().split())
	graph[a].append(b)
	graph[b].append(a)
bridge = set([])
ans = 0
while 1:
	count = 0
	for i in range(1, n + 1):
		if len(graph[i]) == 1:
			count += 1
			a = graph[i][0]
			graph[a].remove(i)
			graph[i] = []
	ans += count
	if count == 0:
		break
	else:
		count = 0
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)