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())
ee = [list(map(int,input().split())) for _ in range(m)]

cnt = 0
for p in range(m):
    e = ee[:p] + ee[p+1:]
    dist = [[float("inf")]*n for _ in range(n)]
    
    for i in range(m-1):
        s,t = e[i]
        dist[s-1][t-1]=1
        dist[t-1][s-1]=1

    for i in range(n):
        dist[i][i]=0
    
    

    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dist[i][k] != float("inf") and dist[k][j] != float("inf"):
                   dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
    
    

    flag = True
    for i in range(n):
        if flag == False:
            break
        for j in range(n):
            if dist[i][j]==float("inf"):
                cnt += 1
                flag = False
                break
print(cnt)

Solution (Python):


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)

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

ab = []
for _ in range(m):
    a, b = map(int,input().split())
    ab.append((a-1, b-1))
    
ans = 0
for i in range(m):
    uf = UnionFind(n)
    for j, r in enumerate(ab):
        if j == i:
            continue
        a, b = r
        uf.union(a, b)
    if uf.group_count() > 1:
        ans += 1
        
print(ans)

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

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)
    for j in range(m):
        if i != j:
            uf.union(a[j][0]-1, a[j][1]-1)
    if uf.size(0) != n:
        ans += 1
print(ans)

Solution (Python):
import sys
import collections

input_methods=['clipboard','file','key']
using_method=0
input_method=input_methods[using_method]

tin=lambda : map(int, input().split())
lin=lambda : list(tin())
mod=1000000007



def is_bridge(n, pi, to_info):
	is_a=[-1]*n
	q =collections.deque()
	q.append(0)
	
	while q:
		pos = q.popleft()
		for to in to_info[pos]:
			if pos in pi and to in pi:
				continue
			if is_a[to] != -1:
				continue
			is_a[to]=1
			q.append(to)
	
	return min(is_a) == -1


def main():
	
	n, m = tin()
	
	path = []
	to_info = [[] for _ in range(n)]
	for _ in range(m):
		a, b = tin()
		path.append([a-1, b-1])
		to_info[a-1].append(b-1)
		to_info[b-1].append(a-1)
		
	ret = 0
	
	for pi in path:
		if is_bridge(n, pi, to_info):
			
			ret += 1
	print(ret)
	
	

isTest=False

def pa(*vl):
	if not isTest:
		return
	for v in vl:
		print(v)
		
def input_clipboard():
	import clipboard
	input_text=clipboard.get()
	input_l=input_text.splitlines()
	for l in input_l:
		yield l

if __name__ == "__main__":
	if sys.platform =='ios':
		if input_method==input_methods[0]:
			ic=input_clipboard()
			input = lambda : ic.__next__()
		elif input_method==input_methods[1]:
			sys.stdin=open('inputFile.txt')
		else:
			pass
		isTest=True
	else:
		pass
		
			
	ret = main()
	if ret is not None:
		print(ret)

Solution (Python):
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())
uf=UnionFind(n)
l=[]
ans=0
for i in range(m):
  a,b=map(int,input().split())
  l.append([a,b])
for i in range(m):
  for j in range(m):
    if i!=j:
      uf.union(l[j][0]-1,l[j][1]-1)
  if uf.group_count()!=1:
    ans+=1
  uf.__init__(n)
print(ans)

Solution (Python):
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 = map(int, input().split())
AB = [list(map(lambda x: int(x)-1, 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)

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

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

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

Solution (Python):
import sys



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


def input_int():
    return int(input())


def input_int_list():
    return [int(i) for i in input().split()]


def dfs(G, i):
    seen = set([i])
    stack = [i]
    cnt = 0
    while stack:
        node = stack.pop()
        cnt += 1
        for _n in G[node]:
            if _n not in seen:
                seen.add(_n)
                stack.append(_n)
    return cnt


def main():
    from collections import defaultdict
    G = defaultdict(set)
    edge = []
    n, m = input_int_list()

    for _ in range(m):
        a, b = input_int_list()
        G[a].add(b)
        G[b].add(a)
        edge.append((a, b))

    ans = 0
    
    
    for a, b in edge:
        G[a].remove(b)
        G[b].remove(a)
        cnt = dfs(G, 1)
        if cnt < n:
            ans += 1
        G[a].add(b)
        G[b].add(a)

    print(ans)

    return


if __name__ == "__main__":
    main()

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())
ab_s = [list(map(int, input().split())) for _ in range(M)]
answer = 0
for i in range(M):
    uf = UnionFind(N)
    for j in range(M):
        if i == j:
            continue
        a,b = map(int, ab_s[j])
        uf.Unite(a,b)
    a,b = map(int, ab_s[i])
    if not uf.isSameGroup(a,b):
        answer += 1
print(answer)

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

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 9)

def int1(x): return int(x) - 1
def II(): return int(input())
def MI(): return map(int, input().split())
def MI1(): return 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')







"""
https://note.nkmk.me/python-union-find/
素集合データ構造

:parameter
union(x, y): 2つの集合を一つに併合する
find(x): xがどの集合に属しているかを判定する
size(x): 要素xが属するグループのサイズ（要素数）を返す
same(x, y): 要素x, yが同じグループに属するかどうかを返す
members(x): 要素xが属するグループに属する要素をリストで返す
roots(): 全ての根の要素をリストで返す
group_count(): グループの数を返す
all_group_members(): 辞書を返す。　key = ルート要素, value = そのグループに含まれる要素のリスト
__str__(): print()での表示用。ルート要素: [そのグループに含まれる要素のリスト]を文字列で返す
"""
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)

if __name__ == '__main__':
    solve()

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 9)

def int1(x): return int(x) - 1
def II(): return int(input())
def MI(): return map(int, input().split())
def MI1(): return 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)

if __name__ == '__main__':
    solve()

Solution (Python):
from collections import deque
n, m = map(int, input().split())
graph = [[] for _ in range(n)]

cand = []
for _ in range(m):
  a, b = map(int, input().split())
  cand.append((a-1, b-1))
  graph[a-1].append(b-1)
  graph[b-1].append(a-1)

def bfs(i):
  dist = [-1] * n
  dist[i] = 0
  d = deque()
  d.append(i)
  while d:
    v = d.popleft()
    for j in graph[v]:
      if dist[j] != -1:
        continue
      dist[j] = dist[v] + 1
      d.append(j)
  return dist

def judge(c):
  graph[c[0]].remove(c[1])
  graph[c[1]].remove(c[0])
  dist = bfs(0)
  graph[c[0]].append(c[1])
  graph[c[1]].append(c[0])
  for d in dist:
    if d == -1:
      return True
  return False

ans = 0
for c in cand:
  if judge(c):
    ans += 1
print(ans)

Solution (Python):
import sys
import math
from collections import defaultdict, deque, Counter
from copy import deepcopy
from bisect import bisect, bisect_right, bisect_left
from heapq import heapify, heappop, heappush
    
input = sys.stdin.readline
def RD(): return input().rstrip()
def F(): return float(input().rstrip())
def I(): return int(input().rstrip())
def MI(): return map(int, input().split())
def MF(): return map(float,input().split())
def LI(): return list(map(int, input().split()))
def TI(): return tuple(map(int, input().split()))
def LF(): return list(map(float,input().split()))
def Init(H, W, num): return [[num for i in range(W)] for j in range(H)]
    
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())

def main():
    N, M = MI()
    ans = 0
    L = tuple(TI() for i in range(M))
    seq = [i for i in range(M)]
    
    for i in seq:
        Union = UnionFind(N)
        for j in filter(lambda x: x != i, seq):
            a, b = L[j]
            Union.union(a-1, b-1)
            
        a, b = L[i]
        if not Union.same(a-1,b-1):
            ans += 1
            
    print(ans)   
        
    
        
    
if __name__ == "__main__":
    main()

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

Solution (Python):


N,M=map(int,input().split())
ans = 0
L = []
def UF(l):
    
    par=[0]
    
    rank=[0]
    
    
    for i in range(1,N+1):
        par.append(i)
        rank.append(0)
    
    
    def find(x):
        
        if par[x]==x:
            return x
        else:
            
            par[x] = find(par[x])
            
            return par[x]
    
    
    def unite(x,y):
        
        root_x=find(x)
        root_y=find(y)
    
        
        if root_x == root_y:
            return
    
        
        if rank[root_x] < rank[root_y]:
            par[root_x] = root_y
    
        else:
            par[root_y] = root_x
    
        
        if rank[root_x]==rank[root_y]:
            rank[root_x]+=1
    
    
    def same(x,y):
        return find(x)==find(y)
    for i in range(M-1):
        a = l[i][0]
        b = l[i][1]
        unite(a, b)
    for i in range(1, N):
        if not same(i, i+1):
            return True


for i in range(M):
    L.append(list(map(int,input().split())))

for i in range(M):
    l = L[0:i] + L[i+1:]
    if UF(l):
        ans += 1
print(ans)

Solution (Python):

N,M=map(int,input().split())
ans = 0
L = []
def UF(l):
    
    par=[0]
    
    rank=[0]
    
    
    for i in range(1,N+1):
        par.append(i)
        rank.append(0)
    
    
    def find(x):
        
        if par[x]==x:
            return x
        else:
            
            par[x] = find(par[x])
            
            return par[x]
    
    
    def unite(x,y):
        
        root_x=find(x)
        root_y=find(y)
    
        
        if root_x == root_y:
            return
    
        
        if rank[root_x] < rank[root_y]:
            par[root_x] = root_y
    
        else:
            par[root_y] = root_x
    
        
        if rank[root_x]==rank[root_y]:
            rank[root_x]+=1
    
    
    def same(x,y):
        return find(x)==find(y)
    for i in range(M-1):
        a = l[i][0]
        b = l[i][1]
        unite(a, b)
    for i in range(1, N):
        if not same(i, i+1):
            return True


for i in range(M):
    L.append(list(map(int,input().split())))

for i in range(M):
    l = L[0:i] + L[i+1:]
    if UF(l):
        ans += 1
print(ans)

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

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.p = [i for i in range(n)]
        self.components = n  

    def root(self, x):
        if self.p[x] != x:
            stack = [x]
            while True:
                top = stack[-1]
                if self.p[top] == top:
                    break
                else:
                    stack.append(self.p[top])
            for v in stack:
                self.p[v] = top
        return self.p[x]
    
    def unite(self, x, y):
        x, y = self.root(x), self.root(y)
        if x != y:
            self.p[x] = y
            self.components -= 1
    
    def same(self, x,y):
        return (self.root(x) == self.root(y))

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: continue
        UF.unite(edges[j][0]-1, edges[j][1]-1)
    
    if UF.components > 1:
        ans += 1
print(ans)

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

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

Solution (Python):






n,m = 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)

Solution (Python):
N,M=map(int,input().split())
a=[]
b=[]
for e in range(M):
    x,y=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)

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

Solution (Python):
import queue
n, m = map(int, input().split())
route = [[] for _ in range(n)]
vals = []
for _ in range(m):
    a, b = 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)