Problem:
 Score : 300 points    Problem Statement You are given an undirected connected graph with N vertices and M edges that does not contain self-loops and double edges. The i -th edge (1 \leq i \leq M) connects Vertex a_i and Vertex b_i .  An edge whose removal disconnects the graph is called a bridge . Find the number of the edges that are bridges among the M edges.      Notes  A self-loop is an edge i such that a_i=b_i  (1 \leq i \leq M) .  Double edges are a pair of edges i,j such that a_i=a_j and b_i=b_j  (1 \leq i<j \leq M) .  An undirected graph is said to be connected when there exists a path between every pair of vertices.       Constraints  2 \leq N \leq 50  N-1 \leq M \leq min(N(N−1)⁄2,50)  1 \leq a_i<b_i \leq N  The given graph does not contain self-loops and double edges.  The given graph is connected.         Input Input is given from Standard Input in the following format:  N  M  a_1  b_1  a_2  b_2  :  a_M  b_M       Output Print the number of the edges that are bridges among the M edges.        Sample Input 1 7 7
1 3
2 7
3 4
4 5
4 6
5 6
6 7      Sample Output 1 4  The figure below shows the given graph:     The edges shown in red are bridges. There are four of them.       Sample Input 2 3 3
1 2
1 3
2 3      Sample Output 2 0  It is possible that there is no bridge.       Sample Input 3 6 5
1 2
2 3
3 4
4 5
5 6      Sample Output 3 5  It is possible that every edge is a bridge.

Solution (Python):
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)

Solution (Python):
N, M = map(int,input().split())
E = [list(map(int, input().split())) for _ in range(M)]

T = [[0 for _ in range(N)] for _ in range(N)]

for i in range(M):
	a,b = E[i]
	T[a-1][b-1] = 1
	T[b-1][a-1] = 1

def bfs(table, flg, q):
	c = q.pop(0)
	flg[c-1] = 1

	NN = [ind+1 for ind in range(N) if table[c-1][ind] == 1]
	for n in NN:
		if flg[n-1] == 0:
			q.append(n)
	
	if len(q) == 0:
		return flg.count(0)

	return bfs(table, flg, q)

ans = 0

for i in range(M):
	a,b = E[i]
	T[a-1][b-1] = 0
	T[b-1][a-1] = 0
	
	flg = [0 for _ in range(N)]

	cnt = bfs(T, flg, [1])

	if cnt > 0:
		ans += 1

	T[a-1][b-1] = 1
	T[b-1][a-1] = 1

print(ans)

Solution (Python):
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)

Solution (Python):
import sys
import math
from collections import defaultdict

sys.setrecursionlimit(10**7)
def input():
    return sys.stdin.readline()[:-1]

mod = 10**9 + 7

def I(): return int(input())
def II(): return map(int, input().split())
def III(): return list(map(int, input().split()))
def Line(N):
    read_all = [tuple(map(int, input().split())) for _ in range(N)]
    return map(list,zip(*read_all))



class UF(object):
    def __init__(self, n=1):
        self.par = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]

    def find(self, x):
        '''
        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 と y のグループを結合
        '''
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.par[y] = x
            self.size[x] += self.size[y]

    def is_same(self, x, y):
        '''
        x と y が同じグループか否か
        '''
        return self.find(x) == self.find(y)

    def get_size(self, x):
        '''
        x が属するグループの要素数
        '''
        x = self.find(x)
        return self.size[x]

N,M = II()
a,b = Line(M)

ans = 0
for i in range(M):
    uf = UF(N)
    for j in range(M):
        if j==i:
            continue
        else:
            uf.union(a[j]-1,b[j]-1)
    flag = False
    for k in range(N):
        for l in range(k+1,N):
            if not uf.is_same(k,l):
                flag = True
                break
        else:
            continue
        break
    if flag:
        ans += 1

print(ans)

Solution (Python):
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)

Solution (Python):
N, M = map(int, input().split())

A = []
B = []
graph = [[False for i in range(N)] for j in range(N)]
visited = [False for i in range(N)]

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

ans = 0

def dfs(v):
    visited[v] = True
    for v2 in range(N):
        if graph[v][v2]==False:
            continue
        if visited[v2]==True:
            continue
        dfs(v2)

for i in range(M):
    graph[A[i]][B[i]] = False
    graph[B[i]][A[i]] = False
    
    for j in range(N):
        visited[j] = False
               
    dfs(0)
    
    bridges = False
    
    for j in range(N):
        if visited[j]==False:
            bridges = True
            break
        
    if bridges:
        ans += 1
        
    graph[A[i]][B[i]] = True
    graph[B[i]][A[i]] = True

print(ans)

Solution (Python):

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)


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

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

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

        if (self.rank[x] < self.rank[y]):
            self.parent[x] = y
        else:
            self.parent[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):
        count = 0
        for i in range(self.n):
            if self.find(i) == i:
                count += 1

        return count




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

A = [0] * M
B = [0] * M

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

count = 0
for i in range(M):
    uf = UnionFind(N)
    for j in range(M):
        if i == j:
            continue
        uf.unite(A[j], B[j])

    
    for i in range(N):
        uf.find(i)



    if uf.get_parents() > 1:
        count += 1

print(count)

Solution (Python):
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)

Solution (Python):
class UnionFind():
	def __init__(self, n):
		self.n = n
		self.root = [-1]*(n+1)
		self.rank = [0]*(n+1)

	def find(self, x):
		if(self.root[x] < 0):
			return x
		else:
			self.root[x] = self.find(self.root[x])
			return self.root[x]
			
	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if(x == y):
			return 0
		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

	def size(self, x):
		return -self.root[self.find(x)]
		
n,m,*l = map(int,open(0).read().split())
edges = [(a,b) for a,b in zip(l[::2],l[1::2])]
ans = 0
for i in range(m):
	uf = UnionFind(n)
	for j in range(m):
		if i==j:
			continue
		else:
			a,b = edges[j]
			uf.unite(a,b)
	ans += uf.size(a)<n
print(ans)

Solution (Python):
import sys
from collections import deque
input = sys.stdin.readline

class Node:
    def __init__(self, id_):
        self.id = id_
        self.link = []
        self.check = False
        

def main():
    N, M = map(int, input().split())
    
    nodes = [Node(i) for i in range(N+1)]

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

    for i in range(M):
        a, b = ab[i]
        nodes[a].link.append(nodes[b])
        nodes[b].link.append(nodes[a])
    
    ans = 0
    for a, b in ab:
        check = [False] * (N+1)
        q = deque()
        tmp = 0
        q.append(nodes[1])
        check[1] = True
        while len(q) > 0:
            node = q.popleft()
            tmp += 1
            if node.id == a:
                ban_id = b
            elif node.id == b:
                ban_id = a
            else:
                ban_id = -1
            for nex in node.link:
                if nex.id != ban_id and not check[nex.id]:
                    check[nex.id] = True
                    q.append(nex)
        
        if tmp != N:
            ans += 1
    
    print(ans)


if __name__ == "__main__":
    main()

Solution (Python):
n, m = map(int, input().split())
g = [[0 for _ in range(n)] for _ in range(n)]
lis_a = []
lis_b = []
for _ in range(m):
    a, b = map(int, input().split())
    lis_a.append(a-1)
    lis_b.append(b-1)
    g[a-1][b-1] = 1
    g[b-1][a-1] = 1

def dfs(v):
    seen[v] = 1
    ret = 1
    for v2 in range(n):
        if g[v][v2] == 1 and seen[v2] == 0:
            dfs(v2)
    if seen == [1] * n:
        ret = 0
        
    return ret
ans = 0
for i in range(m):
    seen = [0] * n
    g[lis_a[i]][lis_b[i]] = 0
    g[lis_b[i]][lis_a[i]] = 0
    ans += dfs(0)
    g[lis_a[i]][lis_b[i]] = 1
    g[lis_b[i]][lis_a[i]] = 1
print(ans)

Solution (Python):
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()

Solution (Python):

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)

Solution (Python):





from sys import stdin,setrecursionlimit


setrecursionlimit(10**6)
input=stdin.readline

n,m=map(int,input().split())
graph=[[0]*n for _ in range(n)]
v=[list(map(int,input().split())) for _ in range(m)]
l=[0]*n

def dfs(x):
    if l[x]:
        return
    l[x]=1
    for i in range(n):
        if graph[x][i]:
            dfs(i)

for i in v:
    graph[i[0]-1][i[1]-1]=1
    graph[i[1]-1][i[0]-1]=1

ans=0
for i in range(m):
    graph[v[i][1]-1][v[i][0]-1]=0
    graph[v[i][0]-1][v[i][1]-1]=0

    chack=False
    l=[0]*n
    dfs(0)

    for j in l:
        if not j:
            ans+=1
            break
    graph[v[i][1]-1][v[i][0]-1]=1
    graph[v[i][0]-1][v[i][1]-1]=1
print(ans)

Solution (Python):
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)

Solution (Python):
import sys
from collections import deque
input = sys.stdin.readline

def dfs(x):
    if Visited[x]: return
    Visited[x] = True
    for e in AB[x]:
        dfs(e)

n,m = map(int,input().split())
AB = [[] for i in range(n)]
Edges = [];
st = 0
for i in range(m):
    a,b = map(int,input().split())
    if i == 0: st = a-1
    AB[a-1].append(b-1)
    AB[b-1].append(a-1)
    Edges.append((a-1,b-1))
ans = 0
for a,b in Edges:
    AB[a].remove(b);AB[b].remove(a)
    Visited = [False] * n
    dfs(st)
    if not all(Visited):
        ans += 1
        
    AB[a].append(b);AB[b].append(a)
print(ans)

Solution (Python):
import sys
import copy
import  math
import bisect
from collections import *
from operator import itemgetter
"""
from fractions import gcd
def lcm(x, y):
    return (x * y) // gcd(x, y)
"""
stdin = sys.stdin
ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline()


def dfs(v):
    visit[v] = True
    for v2 in range(n):
        if not g[v][v2]:
            continue
        if visit[v2]:
            continue
        dfs(v2)



n, m = na()
g = [[False] * n for i in range(n)]
li = []
for i in range(m):
    a, b = na()
    a -= 1
    b -= 1
    g[a][b] = g[b][a] = True
    li.append((a, b))

visit = [False] * n

ans = 0

for i in range(m):
    a, b = li[i]
    g[a][b] = g[b][a] = False
    for j in range(n):
        visit[j] = False
    dfs(0)
    flag = False
    for j in range(n):
        if not visit[j]:
            flag = True
    if flag:
        ans += 1
    g[a][b] = g[b][a] = True

print(ans)

Solution (Python):
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)

Solution (Python):
class UnionFind():
  def __init__(self, n):
    self.n = n
    self.root = [-1] * (n + 1)
    self.rnk = [0] * (n + 1)

  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.rnk[x] > self.rnk[y]:
      self.root[x] += self.root[y]
      self.root[y] = x
    else:
      self.root[y] += self.root[x]
      self.root[x] = y
      if self.rnk[x] == self.rnk[y]:
        self.rnk[y] += 1

  def isSameGroup(self, x, y):
    return self.Find_Root(x) == self.Find_Root(y)

  def Count(self, x):
    return -self.root[self.Find_Root(x)]
  
N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(M)]
res = 0
for i in range(M):
  uf = UnionFind(N)
  for j in range(M):
    if i == j:
      continue
    uf.Unite(A[j][0], A[j][1])
  for k in range(1, N + 1):
    if k != A[i][0] and k != A[i][1]:
      if uf.Count(k) != N:
        res += 1
      break
print(res)

Solution (Python):


import copy
import itertools

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

all_edge_list = sorted(edge_list, key=lambda x: (x[0], x[1]))
all_node_list = list(set(list(itertools.chain.from_iterable(edge_list))))

bridge_list = []

for removed_edge in all_edge_list:  
    r_a, r_b = removed_edge[0], removed_edge[1]

    
    w_edge_list = copy.copy(all_edge_list)
    w_edge_list.remove((r_a, r_b))

    
    a, b = w_edge_list[0]
    done_node_list = []
    done_node_list.append(a)
    done_node_list.append(b)

    done_edge_list = []
    done_edge_list.append((a, b))

    while True:
        
        connected_edges = [edge for edge in w_edge_list if edge[0] in done_node_list or edge[1] in done_node_list]
        new_edges = set(connected_edges) - set(done_edge_list)
        for edge in new_edges:
            
            done_edge_list.append(edge)
            done_node_list.append(edge[0])
            done_node_list.append(edge[1])
            done_node_list = list(set(done_node_list))
        if not new_edges:
            break

    if len(done_node_list) != len(all_node_list):
        
        bridge_list.append((r_a, r_b))

ans = len(bridge_list)
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, 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[x] += 1


n, m = map(int, input().split())
edges = [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(edges[j][0]-1, edges[j][1]-1)
    c = 0
    for j in range(n):
        if j == uf.find(j):
            c += 1
    if c > 1:
        ans += 1

print(ans)

Solution (Python):
def dfs(v):
    visited[v] = True
    for v2 in range(n):
        if G[v][v2]==1 and visited[v2]==False:
            dfs(v2)
    

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

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

cnt = 0
for i in range(m):
    G[a[i]][b[i]] = G[b[i]][a[i]] = 0
    for j in range(n):
        visited[j] = False
    
    dfs(0)

    if False in visited:
        cnt += 1

    G[a[i]][b[i]] = G[b[i]][a[i]] = 1

print(cnt)

Solution (Python):
class UnionFind:
    def __init__(self, size):
        self.table = [-1 for _ in range(size)]

    def find(self, x):
        while self.table[x] >= 0:
            x = self.table[x]
        return x

    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] != self.table[s2]:
                if self.table[s1] < self.table[s2]:
                    self.table[s2] = s1
                else:
                    self.table[s1] = s2
            else:
                self.table[s1] += -1
                self.table[s2] = s1
        return


n, m = map(int, input().split())
edges = [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(edges[j][0]-1, edges[j][1]-1)
    c = 0
    for j in range(n):
        if j == uf.find(j):
            c += 1
    if c > 1:
        ans += 1

print(ans)

Solution (Python):
"""


 = sys.stdin.readline().rstrip()
 = list(sys.stdin.readline().rstrip())


 = int(sys.stdin.readline())
 = map(int, sys.stdin.readline().split())
 = list(map(int, sys.stdin.readline().split()))
 = [list(map(int,list(sys.stdin.readline().split()))) for i in range(h)]  


a = 100
b = 0.987654321
print("{0:06d}-{1:6f}".format(a,b))
000100-0.987654


char_list = list("abcd") 
"""

import math
import sys
import itertools
import queue
from fractions import gcd

def lcm(a, b):
    return a * b // gcd(a, b)

mod = 1000000007

if __name__ == "__main__":
    n,m= map(int, sys.stdin.readline().split())

    visited = [False for i in range(n)]
    matrix = [[False for i in range(n)] for j in range(n)]

    a =[]
    b = []

    
    def dfs(v):
        visited[v] = True
        for v2 in range(n): 
            if matrix[v][v2] == False:
                continue
            if visited[v2] == True:
                continue
            dfs(v2) 

    
    for i in range(m):
        _a,_b = map(int,input().split())
        a.append(_a -1)
        b.append(_b -1)
        matrix[a[i]][b[i]] = True
        matrix[b[i]][a[i]] = True
        
        
        
        
        

    
    ans = 0
    for i in range(m):
        matrix[a[i]][b[i]] = False
        matrix[b[i]][a[i]] = False
        

        visited = [False for i in range(n)]
        
        dfs(0)
        

        bridge = False
        for j in range(n):
            if(visited[j] == False):
                bridge=True
        
        if(bridge):
            ans +=1
        matrix[a[i]][b[i]] = matrix[b[i]][a[i]] = True 
        
    print(ans)

Solution (Python):
import collections 
import sys,heapq,bisect,math,itertools,string,queue,datetime
mod = 10**9+7
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpl_str(): return list(sys.stdin.readline().split())

n,m = inpl()
t = []
cnt = [0] * (n+1)
ans = 0
for i in range(m):
    a,b = inpl()
    t.append([a,b])
    cnt[a] += 1
    cnt[b] += 1

while m:
    flag = False
    for i in range(1,n+1):
        if cnt[i] == 1:
            flag = True
            cnt[i] = 0
            ans += 1
            for j in t:
                if j[0] == i:
                    cnt[j[1]] -= 1
                    t.remove(j)
                elif j[1] == i:
                    cnt[j[0]] -= 1
                    t.remove(j)
            break
    if flag == False:
        break
    m -= 1
        
print(ans)

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

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

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

def unite(a , b):
    ra = root(a)
    rb = root(b)
    if ra == rb:
        return
    parent[ra] = rb

ans = 0
for i in range(M):
    parent = [k for k in range(N)]
    for j , e in enumerate(edge):
        if j == i:
            continue
        a , b = e
        unite(a , b)
    a , b = edge[i]
    if not is_same(a , b):
        ans += 1
print(ans)

Solution (Python):
import copy
n, m = map(int, input().split(' '))
db = [[] for _ in range(n)]
a = []
b = []
for i in range(m):
    a_ ,b_ = map(int, input().split(' '))
    db[a_-1].append(b_-1)
    db[b_-1].append(a_-1)
    a.append(a_-1)
    b.append(b_-1)

def dfs(num):
    if checker[num] == 1:
        return 0
    checker[num] = 1
    for k in db_1[num]:
        dfs(k)
    return 0

counter = 0
for i in range(m):
    checker = [0 for _ in range(n)]
    db_1 = copy.deepcopy(db)
    db_1[a[i]].remove(b[i])
    db_1[b[i]].remove(a[i])
    dfs(a[i])
    if all(checker[s] == 1 for s in range(len(checker))):
        continue
    else:
        counter += 1
print(counter)

Solution (Python):
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)

Solution (Python):
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)

Solution (Python):
N, M = map(int, input().split())
edge = [[] for _ in range(N)]
ab = [list(map(int, input().split())) for _ in range(M)]
for i in range(M):
    a, b = ab[i][0] - 1, ab[i][1] - 1
    edge[a].append(b)
    edge[b].append(a)

def f(now):
    vi[now] = True
    for to in edge[now]:
        if (now == a and to == b) or (now == b and to == a):
            pass
        else:
            if vi[to] != True:
                f(to)

ans = 0
for s in ab:
    a = s[0] - 1
    b = s[1] - 1
    vi = [False] * N
    f(0)
    for v in vi:
        if not v:
            ans += 1
            break

print(ans)

Solution (Python):
import copy

def j(n):
    if n:print("Yes")
    else:print("No")
    exit(0)
rem = 10 ** 9 + 7

"""
def ct(x,y):
    if (x>y):print("+")
    elif (x<y): print("-")
    else: print("?")
"""

def ip():
    return int(input())
def iprow():
    return [int(i) for i in input().split()]
def ips():
    return (int(i) for i in input().split())
def ipmultiplerow(n):
    a = []
    for i in range(n):
        a.append(ip())
    return a
def printrow(a):
    for i in a:
        print(i)

n,m = ips()
a = []
s = 0
for i in range(m):
    x,y = ips()
    a.append([x,y])
connection = [[] for i in range(n+1)]
for i in range(m):
    [x,y] = a[i]
    connection[x].append(y)
    connection[y].append(x)
for loop in range(50):
    for i in range(1,n+1):
        if len(connection[i]) == 1:
            temp = connection[i][0]
            d = connection[temp].index(i)
            connection[temp].pop(d)
            s+=1
            connection[i].pop(0)
print(s)

Solution (Python):
import copy

def j(n):
    if n:print("Yes")
    else:print("No")
    exit(0)
rem = 10 ** 9 + 7

"""
def ct(x,y):
    if (x>y):print("+")
    elif (x<y): print("-")
    else: print("?")
"""

def ip():
    return int(input())
def iprow():
    return [int(i) for i in input().split()]
def ips():
    return (int(i) for i in input().split())
def ipmultiplerow(n):
    a = []
    for i in range(n):
        a.append(ip())
    return a
def printrow(a):
    for i in a:
        print(i)

n,m = ips()
a = []
s = 0
for i in range(m):
    x,y = ips()
    a.append([x,y])
connection = [[] for i in range(n+1)]
for i in range(m):
    [x,y] = a[i]
    connection[x].append(y)
    connection[y].append(x)
for loop in range(100):
    for i in range(1,n+1):
        if len(connection[i]) == 1:
            temp = connection[i][0]
            d = connection[temp].index(i)
            connection[temp].pop(d)
            s+=1
            connection[i].pop(0)
print(s)

Solution (Python):
def dfs(num):
  global visited
  for next_num in edge[num]:
    if visited[next_num]:
      continue
    if has_edge[num][next_num]:
      visited[next_num]=1
      dfs(next_num)
      
N,M = map(int,input().split())
ab = []
edge = [[] for x in range(N+1)]
has_edge = [[0 for x in range(N+1)] for x in range(N+1)]
for i in range(M):
  a,b = map(int,input().split())
  ab.append([a,b])
  edge[a].append(b)
  edge[b].append(a)
  has_edge[a][b] = 1
  has_edge[b][a] = 1
  
count = 0
for a,b in ab:
  visited = [0 for x in range(N+1)]
  visited[1] = 1
  has_edge[a][b] = 0
  has_edge[b][a] = 0
  dfs(1)
  if sum(visited) != N:
    count += 1
  has_edge[a][b] = 1
  has_edge[b][a] = 1
print(count)

Solution (Python):
from collections import defaultdict

def solve(graph, m, brg):
  ans = 0
  for i in range(m):
    if len(graph[i]) == 1 and set(sorted([graph[i][0], i])) not in brg:
      graph[graph[i][0]].remove(i)
      brg.append(set(sorted([graph[i][0], i])))
      ans += 1
  return ans, graph

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

brg = []
ans = 0
result = -1
while result != 0:
  result, graph = solve(graph, m, brg)
  ans += result
print(ans)

Solution (Python):


import sys
sys.setrecursionlimit(500000)

def dfs(i):
    global visited,neighbor
    visited[i] = 1
    for j in [k for k in range(N) if neighbor[i][k]==1]:
        if visited[j] == 1:
            continue
        dfs(j)


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

neighbor = [[0 for i in range(N)] for j in range(N)]
for i in range(M):
    neighbor[ab[i][0]][ab[i][1]] = 1
    neighbor[ab[i][1]][ab[i][0]] = 1
for i in range(M):
    neighbor[ab[i][0]][ab[i][1]] = 0
    neighbor[ab[i][1]][ab[i][0]] = 0
    visited = [0 for i in range(N)]
    dfs(0)
    neighbor[ab[i][0]][ab[i][1]] = 1
    neighbor[ab[i][1]][ab[i][0]] = 1
    if sum(visited) != N:
        ans += 1
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        """
        ノード数nの配列を作る
        親の番号を格納する
        -> 自分が根だった場合は、-(その集合のサイズ)とする
        作るときはparentの値を全て-1にする
        こうすると全てバラバラになる
        """
        self.parent = [-1 for _ in range(n)]
 
    def root(self, x):
        """
        要素xの根の番号を返す
        """
        if self.parent[x] < 0:
            
            return x
        
        
        self.parent[x] = self.root(self.parent[x])
        return self.parent[x]
 
    def size(self, x):
        """
        要素xの所属するグループの頂点数を調べる
        根のparentにサイズが格納されている
        """
        return -self.parent[self.root(x)]
 
    def merge(self, x, y):
        """
        xとyを結合する
        """
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return False
 
        
        if self.parent[x] > self.parent[y]:
            x, y = y, x
        self.parent[x] += self.parent[y]
        self.parent[y] = x
        return True
    
    def issame(self, x, y): 
        return self.root(x) == self.root(y)

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

for i in range(M):
    UF = UnionFind(N)
    for j in range(M):
        if i == j:
            continue
        UF.merge(ab[j][0]-1,ab[j][1]-1)
    if UF.size(0) == N:
        continue
    ans += 1

print(ans)

Solution (Python):
(n, m) = map(int, input().split())
a = []
b = []
graph = [[False for _ in range(n)] for _ in range(n)]
for _ in range(m):
    (a_i, b_i) = map(int, input().split())
    a_i -= 1
    b_i -= 1
    graph[a_i][b_i] = True
    graph[b_i][a_i] = True
    a.append(a_i)
    b.append(b_i)


def dfs(v):
    visit[v] = True
    for i in range(n):
        if not graph[v][i]:
            continue
        if visit[i]:
            continue
        dfs(i)


ans = 0
for i in range(m):
    graph[a[i]][b[i]] = False
    graph[b[i]][a[i]] = False
    visit = [False for _ in range(n)]
    dfs(0)
    bridge = False
    for j in range(n):
        if not visit[j]:
            bridge = True
            break
    if bridge:
        ans += 1
    graph[a[i]][b[i]] = True
    graph[b[i]][a[i]] = True

print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(20000000)

def dfs(num):
    global visited, edge, has_edge
    for next_num in edge[num]:
        if visited[next_num]:
            continue
        if has_edge[num][next_num]:
            visited[next_num] = 1
            dfs(next_num)


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

count = 0
for a, b in ab:
    visited = [0 for _ in range(n+1)]
    visited[1] = 1
    has_edge[a][b] = 0
    has_edge[b][a] = 0
    dfs(1)
    if sum(visited) != n:
        count += 1
    has_edge[a][b] = 1
    has_edge[b][a] = 1
print(count)