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):
from collections import deque
n,m = tuple(map(int,input().split()))

edge = []

for i in range(m):
  edge.append(tuple(map(lambda a:int(a)-1,input().split())))
  
matrix = [[0]*n for _ in range(n)]
  
for a,b in edge:
  matrix[a][b] = 1
  matrix[b][a] = 1
  
ans = 0

for a,b in edge:
  matrix[a][b] = 0
  matrix[b][a] = 0
  
  checked = [False]*n
  queue = deque([0])
  while(len(queue)>0):
    q = queue.popleft()
    if checked[q]:
      continue
    else:
      checked[q] = True
      mat = matrix[q]
      for i in range(n):
        if mat[i] == 1:
          queue.append(i)
  if not all(checked):
    ans+=1
  
  matrix[a][b] = 1
  matrix[b][a] = 1

print(ans)

Solution (Python):
class UnionFind :
    def __init__(self, size) :
        self.parent = list(range(size))
        self.height = [0] * size
        self.size = [1] * size
        self.component = size

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

    def union(self, index1, index2) :  
        root1 = self.root(index1)
        root2 = self.root(index2)

        if root1 == root2 :  
            return

        self.component -= 1  

        if self.height[root1] < self.height[root2] :
            self.parent[root1] = root2  
            self.size[root2] += self.size[root1]
        else :
            self.parent[root2] = root1  
            self.size[root1] += self.size[root2]
            if self.height[root1] == self.height[root2] :
                self.height[root1] += 1
        return

    def isSameRoot(self, index1, index2) :
        return self.root(index1) == self.root(index2)

    def sizeOfSameRoot(self, index) :
        return self.size[self.root(index)]

    def getComponent(self) :
        return self.component

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

edges = [tuple(map(lambda a: int(a) - 1, input().split())) for _ in range(M)]

def isBride(i):
    tree = UnionFind(N)
    for j, (a, b) in enumerate(edges):
        if i == j:
            continue
        tree.union(a, b)
    return tree.getComponent() > 1

print(len([0 for i in range(M) if isBride(i)]))

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

def dfs(used,count,v):

    used[v]=True
    c=count+1
    ev=e[v]
    for ei in ev:
        if(used[ei]):
            continue
        else:
            c=dfs(used,c,ei)
    return c

ans=0
for i in range(m):
    a,b=eab[i]
    e[a].remove(b)
    e[b].remove(a)
    ci=dfs([False for _ in range(n+1)],0,1)
    if(ci!=n):
        ans+=1
    e[a].append(b)
    e[b].append(a)
print(ans)

Solution (Python):
from collections import deque
from heapq import heapify,heappop,heappush,heappushpop
from copy import copy,deepcopy
from itertools import product,permutations,combinations,combinations_with_replacement
from collections import defaultdict,Counter
from bisect import bisect_left,bisect_right


from functools import reduce
from pprint import pprint

INF = float("inf")

def mycol(data,col):
    return [ row[col] for row in data ]

def mysort(data,col,reverse_flag):
    data.sort(key=lambda x:x[col],reverse=reverse_flag)
    return data

def mymax(data):
    M = -1*float("inf")
    for i in range(len(data)):
        m = max(data[i])
        M = max(M,m)
    return M

def mymin(data):
    m = float("inf")
    for i in range(len(data)):
        M = min(data[i])
        m = min(m,M)
    return m

def mycount(ls,x):
    
    l = bisect_left(ls,x)
    r = bisect_right(ls,x)
    return (r-l)

def myoutput(ls,space=True):
    if space:
        if len(ls)==0:
            print(" ")
        elif type(ls[0])==str:
            print(" ".join(ls))
        elif type(ls[0])==int:
            print(" ".join(map(str,ls)))
        else:
            print("Output Error")
    else:
        if len(ls)==0:
            print("")
        elif type(ls[0])==str:
            print("".join(ls))
        elif type(ls[0])==int:
            print("".join(map(str,ls)))
        else:
            print("Output Error")

def I():
    return int(input())

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

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

def CI(n):
    return [ int(input()) for _ in range(n) ]

def LI(n):
    return [ list(map(int,input().split())) for _ in range(n) ]

def S():
    return input()

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

def RS():
    return list(input().split())

def CS(n):
    return [ input() for _ in range(n) ]

def LS(n):
    return [ list(input().split()) for _ in range(n) ]

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 = MI()
ab = LI(m)

ans = 0
for i in range(m):
    uf = UnionFind(n)
    for j in range(m):
        if j==i:
            pass
        else:
            a = ab[j][0] - 1
            b = ab[j][1] - 1
            uf.union(a,b)
    if uf.size(0)==n:
        pass
    else:
        ans += 1
print(ans)

Solution (Python):
import sys
from collections import Counter
from collections import deque
def input(): return sys.stdin.readline().strip()
def mp(): return map(int,input().split())
def lmp(): return list(map(int,input().split()))

n,m=mp()
edge=[lmp() for i in range(m)]
ans=0
for _ in range(m):
    l=[[] for i in range(n+1)]
    que=deque()
    ch=[0]*(n+1)
    ch[0]=1
    for i in range(m):
        if i!=_:
            l[edge[i][0]].append(edge[i][1])
            l[edge[i][1]].append(edge[i][0])
    q=1
    que.append(l[q])
    ch[1]=1
    while len(que):
        q=que.pop()
        for j in range(len(q)):
            if ch[q[j]]==0:
                que.append(l[q[j]])
                ch[q[j]]=1
    b=0
    for k in range(n+1):
        if ch[k]==0:
            b=1
    if b==1:
        ans+=1
print(ans)

Solution (Python):
import sys
from collections import Counter
from collections import deque
def input(): return sys.stdin.readline().strip()
def mp(): return map(int,input().split())
def lmp(): return list(map(int,input().split()))

n,m=mp()
edge=[lmp() for i in range(m)]
ans=0
for _ in range(m):
    l=[[] for i in range(n+1)]
    que=deque()
    ch=[0]*(n+1)
    ch[0]=1
    for i in range(m):
        if i!=_:
            l[edge[i][0]].append(edge[i][1])
            l[edge[i][1]].append(edge[i][0])
    q=1
    que.append(l[q])
    ch[1]=1
    while len(que):
        q=que.pop()
        for j in range(len(q)):
            if ch[q[j]]==0:
                que.append(l[q[j]])
                ch[q[j]]=1
    b=0
    for k in range(n+1):
        if ch[k]==0:
            b=1
    if b==1:
        ans+=1
print(ans)

Solution (Python):
import collections
N, M = map(int, input().split())
ab = [tuple(map(int, input().split())) for i in range(M)]

G = [set() for i in range(N)]

for a, b in ab:
    a -= 1
    b -= 1
    G[a].add(b)
    G[b].add(a)

ans = 0
for a, b in ab:
    a -= 1
    b -= 1
    q = collections.deque([0])
    r = [1]*N
    r[0] = 1
    while(q):
        x = q.popleft()
        for y in G[x]:
            if (x == a and y == b) or (x == b and y == a):
                continue
            else:
                if r[y]:
                    r[y] = 0
                    q.append(y)
    if sum(r) > 0:
        ans += 1
print(ans)

Solution (Python):
from collections import *

def bfs():
    q = deque([0])
    visited = [False]*N
    visited[0] = True
    
    while q:
        v = q.popleft()
        
        for nv in range(N):
            if G[v][nv]==1:
                if not visited[nv]:
                    visited[nv] = True
                    q.append(nv)
    
    return False in visited
    
N, M = map(int, input().split())
G = [[0]*N for _ in range(N)]
edges = []

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

ans = 0

for a, b in edges:
    G[a][b] = 0
    G[b][a] = 0
    
    if bfs():
        ans += 1
    
    G[a][b] = 1
    G[b][a] = 1

print(ans)

Solution (Python):
from scipy.sparse.csgraph import floyd_warshall
from copy import deepcopy

def check(a):
    dist = floyd_warshall(a)

    for i in dist:
        if float("inf") in i:
            return True
    return False

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

edge = [[float("inf") for i in range(N)] for j in range(N)]


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

ans = 0
for a,b in ab:
    tmp = deepcopy(edge)
    tmp[a-1][b-1] = float("inf")
    tmp[b-1][a-1] = float("inf")

    if check(tmp):
        ans += 1

print(ans)

Solution (Python):
import sys
input = lambda: sys.stdin.readline().rstrip() 
sys.setrecursionlimit(10**7)
INF = 10**20
def I(): return int(input())
def F(): return float(input())
def S(): return input()
def LI(): return [int(x) for x in input().split()]
def LI_(): return [int(x)-1 for x in input().split()]
def LF(): return [float(x) for x in input().split()]
def LS(): return input().split()

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 same(self, x, y):
        return self.find(x) == self.find(y)

def resolve():
    N, M = LI()
    ab = [LI_() for _ in range(M)]

    ans = 0
    for i in range(M):
        uf = UnionFind(N)
        for j in range(M):
            if j!=i:
                uf.unite(ab[j][0], ab[j][1])
        if not uf.same(ab[i][0], ab[i][1]):
            ans += 1

    print(ans)


if __name__ == '__main__':
    resolve()

Solution (Python):

import sys


def f(N, M, a, b, skip):
    uf = UnionFind(N)
    for i, (aa, bb) in enumerate(zip(a, b)):
        if i == skip:
            continue
        uf.union(aa-1, bb-1)
    return uf.size(0) != N

def solve(N: int, M: int, a: "List[int]", b: "List[int]"):
    def g(skip):
        return f(N, M, a, b, skip)
    return sum(map(g, range(M)))
        



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  
    M = int(next(tokens))  
    a = [int()] * (M)  
    b = [int()] * (M)  
    for i in range(M):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    print(solve(N, M, a, b))


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 test():
    import doctest
    doctest.testmod()

if __name__ == '__main__':
    
    main()

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0] * n
        self.size = [1] * n

    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 unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = x
            self.size[x] += self.size[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    
    def same(self, x, y):
        if self.find(x) == self.find(y):
            return True
        else:
            return False


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

ans = 0
for i in range(M):
    UF = UnionFind(N)

    for j in range(M):
        a, b = ab[j]
        if j != i:
            UF.unite(a-1, b-1)
    s = set()
    for j in range(N):
        s.add(UF.find(j))
    
    if len(s) > 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)]


def is_bridge(n, ab, i):
    uni = UnionFind(n)
    for j, val in enumerate(ab):
        if i == j:
            continue
        else:
            uni.Unite(val[0]-1, val[1]-1)
    if uni.Count(0) == n:
        return False
    else:
        return True


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

ret = 0

for i in range(m):
    if is_bridge(n, ab, i):
        ret += 1

print(ret)

Solution (Python):
n, m = list(map(int, input().split()))


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


uf = UnionFind(n)
al = [0] * m
bl = [0] * m
for i in range(m):
    al[i], bl[i] = map(int, input().split())

ans = 0
for i in range(m):
    uf = UnionFind(n)
    for j in range(m):
        if i == j:
            continue
        else:
            uf.union(al[j]-1, bl[j]-1)
    if uf.size(0) == n:
        continue
    else:
        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 same(self, x, y):
        return self.find(x) == self.find(y)

    def nums(self,x):
        return abs(self.parents[self.find(x)])

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

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

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

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())
ans = 0
for i in range(M):
    uf = UnionFind(N)
    for j in range(M):
        if j!=i:
            uf.union(A[j]-1,B[j]-1)
    if len(uf.roots())>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 same(self, x, y):
        return self.find(x) == self.find(y)

    def nums(self,x):
        return abs(self.parents[self.find(x)])

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

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

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

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())
ans = 0
for i in range(M):
    uf = UnionFind(N)
    for j in range(M):
        if j!=i:
            uf.union(A[j]-1,B[j]-1)
    if len(uf.roots())>1:
        ans += 1
print(ans)

Solution (Python):

from collections import deque
N, M = map(int, input().split())
edge = []
for _ in range(M):
    edge.append(list(map(int, input().split())))
ans = 0 
for i in range(M):
    done = [True for _ in range(N + 1)]
    renketu = [[] for _ in range(N + 1)]
    for j in [k for k in range(M) if k != i]:
        a, b = edge[j][0], edge[j][1]
        renketu[a].append(b)
        renketu[b].append(a)
    q = deque([1])
    while q:
        now = q.pop()
        done[now] = False

        for r in renketu[now]:
            if done[r]:
                q.append(r)
    if sum(done) > 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 same(self, x, y):
        return self.find(x) == self.find(y)
        
import numpy as np
N, M = map(int, input().split())
edge = []
for _ in range(M):
    edge.append(list(map(int, input().split())))
ans = 0 
for i in range(M):
    unionfind = UnionFind(N)
    for j in [k for k in range(M) if k != i]:
        a, b = edge[j][0] - 1, edge[j][1] - 1
        unionfind.union(a, b)
    if np.count_nonzero(np.array(unionfind.parents) < 0) >= 2:
        ans += 1
print(ans)

Solution (Python):

from collections import defaultdict, Counter
N, M = map(int, input().split())
edge = [[] for _ in range(N + 1)]
cnt_dict = defaultdict(int)

for _ in range(M):
    a, b = map(int, input().split())
    edge[a].append(b)
    cnt_dict[a] += 1
    edge[b].append(a)
    cnt_dict[b] += 1

ans = 0
while True:
    cnt = Counter(cnt_dict).most_common()
    if cnt[-1][1] > 1:
        break
    elif cnt[-1][1] == 1:
        ans += 1
        key = cnt[-1][0]
        cnt_dict[key] = float("inf")
        for i in range(1, N + 1):
            if key in set(edge[i]):
                cnt_dict[i] -= 1
                edge[i].remove(key)
    else:
        break
print(ans)

Solution (Python):

import sys
sys.setrecursionlimit(10**9)
INF=10**18
MOD=10**9+7
input=lambda: sys.stdin.readline().rstrip()
YesNo=lambda b: bool([print('Yes')] if b else print('No'))
YESNO=lambda b: bool([print('YES')] if b else print('NO'))
int1=lambda x:int(x)-1

def main():
    N,M=map(int,input().split())
    edge=[]
    for i in range(M):
        a,b=map(int1,input().split())
        edge.append((a,b))
    class UnionFind:
        def __init__(self,n):
            self.par=[i for i in range(n)]
            self.siz=[1]*n
            
        def root(self,x):
            while self.par[x]!=x:
                self.par[x]=self.par[self.par[x]]
                x=self.par[x]
            return x
        
        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]:
                x,y=y,x
            self.siz[x]+=self.siz[y]
            self.par[y]=x
            return True
        
        def is_same(self,x,y):
            return self.root(x)==self.root(y)
        
        def size(self,x):
            return self.siz[self.root(x)]
    ans=0
    for i in range(M):
        u=UnionFind(N)
        for j in range(M):
            if i==j:
                continue
            u.unite(edge[j][0],edge[j][1])
        if u.size(0)<N:
            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 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 is_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 resolve():
    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):
        uf = UnionFind(N)
        
        for j, e in enumerate(E):
            if i == j:
                continue
            uf.union(e[0], e[1])
        
        
        a, b = E[i]
        if not uf.is_same(a, b):
            ans += 1
    print(ans)

if __name__ == "__main__":
    resolve()

Solution (Python):
printn = lambda x: print(x,end='')
inn = lambda : int(input())
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      map(int, input().split())
ins = lambda : input().strip()
DBG = True 
BIG = 10**18
R = 10**9 + 7

def ddprint(x):
  if DBG:
    print(x)

n,m = inm()
dst = [{} for i in range(n+1)]
for i in range(m):
    u,v = inm()
    dst[u][v] = dst[v][u] = i
sm = 0
for i in range(m):
    q = [1]
    done = [False]*(n+1)
    done[0] = done[1] = True
    while len(q)>0:
        x = q.pop()
        for y in dst[x]:
            if done[y] or dst[x][y]==i:
                continue
            done[y] = True
            q.append(y)
    if len([x for x in done if not x])>0:
        sm += 1
print(sm)

Solution (Python):
from scipy.sparse import coo_matrix, csgraph
N, M = map(int, input().split())
points = tuple(tuple(map(lambda n: int(n) - 1, input().split())) for _ in range(M))
matrix = coo_matrix(([1] * M, tuple(zip(*points))), shape=(N, N)).toarray()
total = 0
for point in points:
    matrix[point] = 0
    total += csgraph.connected_components(matrix, directed=False, return_labels=False) != 1
    matrix[point] = 1
print(total)

Solution (Python):
class UnionFind():
    def __init__(self,n):
        self.n=n
        self.root=[-1]*n
        self.rank=[-1]*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

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

    def size(self,x):
        return -self.root[self.Find_Root(x)]

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

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

    def group_members(self):
        return {i:self.members(i) for i in self.roots()}

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


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

ans=0
for i in range(m):
    unionFind=UnionFind(n+1)
    for j,k in enumerate(AB):
        a,b=k
        if i==j:continue
        else:unionFind.Unite(a,b)
    ans +=0 if unionFind.size(1)==n else 1
print(ans)

Solution (Python):
from copy import deepcopy
from collections import deque
from heapq import heappush, heappop


def warshallfloyd(cost,V):
    INF = float("inf")
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if cost[i][k]!=INF and cost[k][j]!=INF:
                    cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j])

    for i in cost:
        if float("inf") in i:
            return False
    
    return True

N,M = map(int,input().split())
edge = [[float("inf") for i in range(N)] for j in range(N)]
ab = []
for _ in range(M):
    a,b = map(int,input().split())
    ab.append([a-1,b-1])
    edge[a-1][b-1] = 1
    edge[b-1][a-1] = 1

ans = 0

for a,b in ab:
    tmp = deepcopy(edge)
    tmp[a][b] = float("inf")
    tmp[b][a] = float("inf")
    if not warshallfloyd(tmp,N):
        ans += 1

print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n)]
        self.rank = [0]*n
    def check(self, x, y):
        if self.find(x) == self.find(y):
            
            return True
        else:
            return False
    def find(self, x):
        if x == self.par[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[y] = x
        else:
            self.par[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

                
n, m = map(int, input().split())
uf = UnionFind(n)
ans = 0
G = []

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

for i in range(m):
    uf = UnionFind(n)
    for j in range(m):
        if i==j:
            continue
        uf.union(G[j][0], G[j][1])
    
    if not uf.check(G[i][0], G[i][1]):
        
        ans += 1
print(ans)