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

    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())
query = []
for i in range(M):
    query.append(list(map(int, input().split())))

ans = 0
for ignore in range(0, M):
    union = UnionFind(N)
    for i, q in enumerate(query):
        if i == ignore:
            a, b = q[0], q[1]
            continue
        union.union(q[0], q[1])

    if not union.same_check(a, b):
        ans += 1

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):
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
import itertools
from itertools import permutations, combinations
import sys
import bisect
import string
import math
import time
from fractions import gcd



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


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


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


def LI_(): return [int(i)-1 for i in input().split()]


def StoI(): return [ord(i)-97 for i in input()]


def ItoS(nn): return chr(nn+97)


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


def show(*inp, end='\n'):
    if show_flg:
        print(*inp, end=end)


YN = ['Yes', 'No']
MOD = 10**9+7
inf = float('inf')
IINF = 10**19
l_alp = string.ascii_lowercase
u_alp = string.ascii_uppercase
ts = time.time()
sys.setrecursionlimit(10**6)



show_flg = True

class UnionFind(object):
    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()
    a = [0] * M
    b = [0] * M
    ans = 0

    for i in range(M):
        _a, _b = MI()
        a[i], b[i] = _a - 1, _b - 1

    for i in range(M):
        uf = UnionFind(N)
        for j in range(M):
            if i == j:
                continue
            uf.union(a[j], b[j])
        if len(uf.roots()) != 1:
            ans += 1

    print(ans)


if __name__ == '__main__':
    main()

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):
n,m=map(int,input().split())
edges=[list(map(int,input().split())) for i in range(m)]
class UnionFind:
    
    
    __slots__ = ["_size", "_first_idx", "_parents"]
    def __init__(self, size: int, first_index: int = 0) -> None:
        self._size = size
        self._first_idx = first_index
        self._parents = [-1] * (size + first_index)
    def find(self, x: int) -> int:
        if self._parents[x] < 0:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]
    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)
    def unite(self, x: int, y: int) -> bool:
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self._parents[x] > self._parents[y]:
            x, y = y, x
        self._parents[x] += self._parents[y]
        self._parents[y] = x
        return True
    def size(self, x: int) -> int:
        return -self._parents[self.find(x)]
    def group_count(self) ->int:
        return sum(1 for i in  self._parents if i<0)-self._first_idx
    def connected(self) ->bool:
        return self._parents[self.find(self._first_idx)]==-self._size
ans=0
for i in range(m):
    f=UnionFind(n,1)
    for j in range(m):
        if j!=i:f.unite(*edges[j])
    if f.group_count()==2:ans+=1

print(ans)

Solution (Python):
from collections import deque
N, M = map(int, input().split())

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

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return False
        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x
        return True

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

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

ans = 0
for i in range(M):
        uf = UnionFind(N)
        for j, (a, b) in enumerate(V):
            if i != j:
                uf.union(a-1, b-1)
        if not uf.same(V[i][0]-1, V[i][1]-1):
            ans += 1
print(ans)

Solution (Python):
from collections import deque
N, M = map(int, input().split())

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

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return False
        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x
        return True

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

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

ans = 0
for i in range(N):
    for j in range(i+1, N):
        uf = UnionFind(N)
        for a, b in V:
            if a-1 == i and b-1 ==j:
                continue
            uf.union(a-1, b-1)
        if not uf.same(i, j):
            ans += 1
print(ans)

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

def get_par(x):
  if x == par_list[x]:
    return x
  else:
    par_list[x] = get_par(par_list[x])
    return par_list[x]
def merge(x,y):
  par_x = get_par(x)
  par_y = get_par(y)
  if par_x != par_y:
    par_list[par_y] = par_x
def is_same(x,y):
  return get_par(x) == get_par(y)

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


answer=0
for i in range(M):
  par_list = list(range(N+1))
  for j in range(M):
    if i==j:
      continue
    a,b=ablist[j]
    merge(a,b)

  comp_set=set()
  for i in range(1,N+1):
    comp_set.add(get_par(i))
  
  if len(comp_set)>1:
    answer+=1
  
print(answer)

Solution (Python):
import bisect

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


class UnionFind:

    def __init__(self, n):
        self.par =  [-1] * n
        self.rank = [0] * n
    
    def root(self,x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.root(self.par[x])
            return self.par[x]

    def union(self, x, y):
        x = self.root(x)
        y = self.root(y)

        if x == y:
            return
        else:
            if self.rank[x] <self.rank[y]:
                self.par[y] += self.par[x] 
                self.par[x] = y
            else:
                self.par[x] += self.par[y]
                self.par[y] = x
                if self.rank[x] == self.rank[y]: 
                    self.rank[x] += 1
    
    def is_same(self, x, y):
        return self.root(x) == self.root(y)

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

Tree = UnionFind(N)
ans = 0
for i in range(1,N+1):
    for j in range(len(bridge[i])):
        erase_a = i
        erase_b = bridge[i][j]
        del bridge[i][j]

        for k in range(1,N+1):
            for l in range(len(bridge[k])):
                Tree.union(k-1,bridge[k][l]-1)
        
        if not Tree.is_same(erase_a-1,erase_b-1):
            ans += 1

        bisect.insort_left(bridge[erase_a],erase_b)

        Tree.__init__(N)

print(ans)

Solution (Python):
import os

import sys

if os.getenv("LOCAL"):
    sys.stdin = open("_in.txt", "r")

sys.setrecursionlimit(10 ** 9)
INF = float("inf")
IINF = 10 ** 18
MOD = 10 ** 9 + 7





def enumerate_bridges(graph):
    """
    橋を列挙する
    http://nupioca.hatenadiary.jp/entry/2013/11/03/200006
    :param list of (list of int) graph:
    """
    N = len(graph)
    ret_bridges = []
    pres = [-1] * N
    lows = [-1] * N
    order = -1
    for v in range(N):
        if pres[v] >= 0:
            continue
        edges = [(None, v, True)]
        while edges:
            v, u, forward = edges.pop()
            if forward:
                if pres[u] >= 0:
                    
                    lows[v] = min(lows[v], lows[u])
                    continue
                edges.append((v, u, False))
                parent, v = v, u
                order += 1
                pres[v] = lows[v] = order
                for u in graph[v]:
                    if u == parent:
                        continue
                    edges.append((v, u, True))
            else:
                if v is None:
                    continue
                if lows[u] == pres[u]:
                    ret_bridges.append((v, u))
                lows[v] = min(lows[v], lows[u])
    return ret_bridges


N, M = list(map(int, sys.stdin.buffer.readline().split()))
AB = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(M)]
graph = [[] for _ in range(N + 1)]
for a, b in AB:
    graph[a].append(b)
    graph[b].append(a)
bridges = enumerate_bridges(graph)
print(len(bridges))

Solution (Python):
from collections import defaultdict


def dfs(i, used, dic, ng):
    for n in dic[i]:
        if n not in used and (i, n) != ng and (n, i) != ng:
            used.add(n)
            dfs(n, used, dic, ng)


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

ret = 0
for a, b in lst:
    used = set()
    dfs(1, used, dic, (a, b))
    if len(used) != N:
        ret += 1
print(ret)

Solution (Python):
from collections import  deque

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

def dfs(st,check):
    check[st]=1
    for th in graph[st]:
        if check[th]==0 :
           dfs(th,check)

ans=0
for i in range(m):
    graph[count[i][0]].remove(count[i][1])
    graph[count[i][1]].remove(count[i][0])
    check = [0 for k in range(n)]
    dfs(0,check)
    if 0 in check:
        ans+=1
    graph[count[i][0]].append(count[i][1])
    graph[count[i][1]].append(count[i][0])

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


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

edges = []

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

ans = 0
for ban in range(m):
    uf = UnionFind(n)
    for i in range(m):
        if ban == i:
            continue

        frm, to = edges[i]
        uf.union(frm, to)

    if len(uf.roots()) > 1:
        ans += 1

print(ans)

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

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

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

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

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

cnt = 0
for i in range(m):
	uf = UnionFind(n)
	for j, e in enumerate(graph):
		if j == i: continue
		a, b = e[0], e[1]
		uf.union(a, b)
	a, b = graph[i][0], graph[i][1]
	if uf.group_size(0) < n: cnt += 1

print(cnt)

Solution (Python):
import sys


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


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

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

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

    def get_parent_list(self):
        return [i for i in range(self.n_nodes) if self.find(i) == i]

    def get_n_groups(self):
        return len(self.get_parent_list())


def main():
    N, M = map(int, input().split())
    edge = [list(map(int, input().split())) for _ in range(M)]
    cnt = 0
    for i in range(M):
        Tree = UnionFind(N)
        for j in range(M):
            if i == j:
                continue
            else:
                Tree.unite(edge[j][0] - 1, edge[j][1] - 1)
        if Tree.get_n_groups() > 1:
            cnt += 1
    print(cnt)


if __name__ == "__main__":
    main()

Solution (Python):
import sys

sys.setrecursionlimit(10 ** 6)
INF = float("inf")
MOD = 10 ** 9 + 7


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


class UnionFind:
    def __init__(self, n_nodes):
        self.n_nodes = n_nodes

        
        
        self.parents = [-1] * n_nodes

    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 get_size(self, x):
        return -self.parents[self.find(x)]

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

    def get_members(self, x):
        parent = self.find(x)
        return [i for i in range(self.n_nodes) if self.find(i) == parent]

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

    def get_n_groups(self):
        return len(self.get_parent_list())

    def get_members_dict(self):
        return {par: self.get_members(par) for par in self.get_parent_list()}


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

    n_groups = base_tree.get_n_groups()
    ans = 0
    for i in range(M):
        tmp_tree = UnionFind(N)
        for j, (a, b) in enumerate(edges):
            if i == j:
                continue

            tmp_tree.union(a, b)

        tmp = tmp_tree.get_n_groups()
        if n_groups != tmp:
            ans += 1

    print(ans)


if __name__ == "__main__":
    main()

Solution (Python):
import sys

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, sys.stdin.readline().strip().split())
edges = []
for _ in range(M):
	a, b = map(int, sys.stdin.readline().strip().split())
	edges.append((a-1, b-1))

ans = 0
for i in range(M):
    uf = UnionFind(N)
    for j, (a, b) in enumerate(edges):
        if i == j:
            continue
        uf.union(a, b)
    
    if uf.group_count() != 1:
        ans += 1

print(ans)

Solution (Python):
limit=50
graph=[[False]*limit for i in range(limit)]
visited=[]*limit

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

n,m=map(int,input().split())
a=[0]*m
b=[0]*m
for i in range(m):
    ai,bi=map(int,input().split())
    a[i]=ai-1
    b[i]=bi-1
    graph[a[i]][b[i]]=True
    graph[b[i]][a[i]]=True
    
ans=0 
for i in range(m):
    graph[a[i]][b[i]]=False
    graph[b[i]][a[i]]=False
    visited=[False]*n
    dfs(0,n,graph,visited)
    bridge=False
    for j in range(n):
        if visited[j]==False:
            bridge=True
    if bridge:
        ans+=1
    graph[a[i]][b[i]]=True
    graph[b[i]][a[i]]=True
    
print(ans)

Solution (Python):
import sys
import math  
import bisect  
import queue  


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


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

    adj = [list() for _ in range(N)]
    for a, b in edge:
        adj[a].append(b)
        adj[b].append(a)

    ans = 0
    for a, b in edge:
        visit = [False for _ in range(N)]
        que = queue.Queue()
        que.put(0)
        while not que.empty():
            c = que.get()
            visit[c] = True
            for n in adj[c]:
                if (c == a and n == b) or (c == b and n == a):
                    continue
                if not visit[n]:
                    que.put(n)
        if sum(visit) != N:
            ans += 1

    print(ans)


if __name__ == '__main__':
    main()

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

par = [i for i in range(n)]
rank = [0]*n

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

def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return False
    if rank[x]<rank[y]:
        par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]:
            rank[x] += 1

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

a = []
b = []

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

ans = 0
for i in range(m):
    par = [k for k in range(n)]
    rank = [0]*n
    
    for j in range(m):
        if i != j:
            unite(a[j],b[j])
            
    
    
    if not same(a[i],b[i]):
        ans+=1
  

print(ans)

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

d = [1]*N
def bfs(graph,s,d,n):
    for v in graph[s]:
        if d[v]:
            d[v] = 0
            bfs(graph,v,d,n)
    if d.count(0) != n:
        return 1
    else:
        return 0
ans = 0
for i in range(M):
    d = [1]*N
    graph1=copy.deepcopy(graph)
    graph1[edge[i][0]].remove(edge[i][1])
    graph1[edge[i][1]].remove(edge[i][0])
    ans+=bfs(graph1,0,d,N)

print(ans)

Solution (Python):
n, m = map(int,input().split())
graph = []
for i in range(n):
    graph.append([])
    for j in range(n):
        graph[i].append(0)

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

def adjacent(g, v):
    adj = []    
    for i in range(n):
        if g[v-1][i] == 1:
            adj.append(i+1)
    return adj


def dfs(g, v):
    visited = []
    stack = []
    
    stack.append(v)
    
    while stack:
        node = stack.pop()
        if node not in visited:
            visited.append(node)
            for w in adjacent(g, node):
                if w not in visited:
                    stack.append(w)
    return visited
            

def cut(g):
    bridge = 0
    for i in range(n):
        for j in range(n):
            if g[i][j] == 1:
                g[i][j] = 0
                g[j][i] = 0
                if len(dfs(g,i+1)) < n:
                    bridge = bridge + 1
                g[i][j] = 1
                g[j][i] = 1
    bridge = bridge // 2
    return bridge

print(cut(graph))

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 resolve():
    N, M = list(map(int, input().split()))
    AB = [list(map(int, input().split())) for i in range(M)]
    cnt = 0
    for i in range(len(AB)):
        uf = UnionFind(N)
        for edge in AB[:i]+AB[i+1:]:
            uf.union(edge[0]-1, edge[1]-1)
        if uf.find(AB[i][0]-1) != uf.find(AB[i][1]-1):
            cnt += 1
    print(cnt)


if '__main__' == __name__:
    resolve()

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 False
        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):
        if self.find(x) == self.find(y):
            return True
        else:
            return False

















import sys
sys.setrecursionlimit(10000000)
mod = 10**9 + 7

def readInts():
  return list(map(int,input().split()))
def main():
    n,m = readInts()
    
    
    bridge = []
    for i in range(m):
        s,e = map(lambda x: int(x) - 1,input().split())
        bridge.append((s,e))
    cnt = 0
    for i in range(m):
        
        Uni = UnionFind(n)
        for j,root in enumerate(bridge,start = 0):
            
            if i == j:
                continue
            s,t = root
            Uni.Union(s,t)
        
        s,t = bridge[i]
        if not Uni.same(s,t): 
            cnt += 1
    print(cnt)


if __name__ == '__main__':
  main()

Solution (Python):
from collections import deque
def main():
    N, M = (int(_) for _ in input().split())
    AB = [[int(_) for _ in input().split()] for __ in range(M)]
    edg = {}
    for ab in AB:
        a, b = ab
        if a in edg.keys():
            edg[a].append(b)
        else:
            edg[a] = [b]
        if b in edg.keys():
            edg[b].append(a)
        else:
            edg[b] = [a]

    def ikeru(i, j):
        visited = [False] * (N+1)
        d = deque()
        visited[i] = True
        for k in edg[i]:
            if k != j:
                d.append(k)
        while d:
            p = d.popleft()
            visited[p] = True
            for k in edg[p]:
                if not visited[k]:
                    d.append(k)
        return visited[j]

    ret = 0
    for i in range(M):
        a, b = AB[i]
        ret += not ikeru(a, b)
    print(ret)
    return

if __name__ == '__main__':
    main()

Solution (Python):
import bisect
def resolve():
    N, M = list(map(int, input().split()))
    AB = [list(map(int, input().split())) for i in range(M)]
    cnt = 0
    for i, edge in enumerate(AB):
        edges = AB[:i]+AB[i+1:]
        if not is_reachable(edges, edge[0], edge[1]):
            cnt += 1
    print(cnt)


def is_reachable(edges, src, dst):
    import collections
    stack = collections.deque()
    stack.append(src)

    while stack:
        pos = stack.pop()
        if pos == dst:
            return True
        _edges = []
        while edges:
            edge = edges.pop()
            if edge[0] == pos:
                stack.append(edge[1])
            elif edge[1] == pos:
                stack.append(edge[0])
            else:
                _edges.append(edge)
        edges = _edges
    return False


if '__main__' == __name__:
    resolve()

Solution (Python):
class UnionFind():
    def __init__(self,num):
        self.n = num         
        self.parents = [-1 for i in range(self.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):
        xx=self.find(x)  
        yy=self.find(y)  
        if xx==yy:
            return     
        else:
            size_xx=abs(self.parents[xx]) 
            size_yy=abs(self.parents[yy]) 
            if size_xx>size_yy:
                xx,yy=yy,xx  

            self.parents[yy]+=self.parents[xx] 
            self.parents[xx]=yy   

    
    def size(self,x):
        xx=self.find(x)
        return abs(self.parents[xx])

    
    def same(self,x,y):
        return 1 if self.find(x)==self.find(y) else 0

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

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

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

    
    def state_grouping(self):
        return list(self.all_group_members().values())

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


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

ans=0
for i in range(m):
    uf=UnionFind(n)
    for j in range(m):
        if j==i:
            continue
        uf.union(*A[j])
    
    if len(uf.roots())!=1:
        ans+=1
print(ans)