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):
V, E = map(int, input().split())
a = [0 for i in range(E)]
b = [0 for i in range(E)]
m = [[0 for i in range(V)] for i in range(V)]
for i in range(E):
    a[i], b[i]=map(int, input().split())
    m[a[i]-1][b[i]-1]+=1
    m[b[i]-1][a[i]-1]+=1
S=0
for n in range(E):
    m[a[n]-1][b[n]-1]-=1
    m[b[n]-1][a[n]-1]-=1
    U=[[] for i in range(V)]
    for i in range(V):
        for j in range(V):
            if m[i][j]!=0:
                U[i].append(j)
    P=[set() for i in range(E+1)]
    P[0].add(0)
    Q=set()
    R=[False for i in range(V)]
    for i in range(1,E+1):
        for u in P[i-1]:
            for v in U[u]:
                if not(R[v]):
                    R[v]=True
                    P[i].add(v)
                    Q.add(v)
        if len(P[i])==0:
            break
    if len(Q)!=V:
        S+=1
    m[a[n]-1][b[n]-1]+=1
    m[b[n]-1][a[n]-1]+=1
print(S)

Solution (Python):
V, E = map(int, input().split())
a = [0 for i in range(E)]
b = [0 for i in range(E)]
m = [[0 for i in range(V)] for i in range(V)]
for i in range(E):
    a[i], b[i]=map(int, input().split())
    m[a[i]-1][b[i]-1]+=1
    m[b[i]-1][a[i]-1]+=1
S=0
for n in range(E):
    m[a[n]-1][b[n]-1]-=1
    m[b[n]-1][a[n]-1]-=1
    U=[[] for i in range(V)]
    for i in range(V):
        for j in range(V):
            if m[i][j]!=0:
                U[i].append(j)
    P=[set() for i in range(E+1)]
    P[0].add(0)
    Q=set()
    R=[False for i in range(V)]
    for i in range(1,E+1):
        for u in P[i-1]:
            for v in U[u]:
                if not(R[v]):
                    R[v]=True
                    P[i].add(v)
                    Q.add(v)
        if len(P[i])==0:
            break
    if len(Q)!=V:
        S+=1
    m[a[n]-1][b[n]-1]+=1
    m[b[n]-1][a[n]-1]+=1
print(S)

Solution (Python):
n,m = map(int,input().split())
branch = dict()
a = []
b = []
for i in range(n+1):
	branch[i] = []
for i in range(m):
	atemp,btemp = map(int,input().split())
	a.append(atemp)
	b.append(btemp)
	branch[atemp].append(btemp)
	branch[btemp].append(atemp)

counter = 0
for i in range(m):
	check = True
	delindex1 = branch[a[i]].index(b[i])
	delindex2 = branch[b[i]].index(a[i])
	del branch[a[i]][delindex1]
	del branch[b[i]][delindex2]
	arrival = [0 for i in range(n+1)]
	q = [1]
	while len(q) >= 1:
		arrival[q[0]]=1
		for k in range(len(branch[q[0]])):
			if arrival[branch[q[0]][k]] == 0:
				q.append(branch[q[0]][k])
		q.pop(0)

	for k in range(1,n+1):
		if arrival[k] == 0:
			check = False
	if check==False:
		counter += 1
	branch[a[i]].append(b[i])
	branch[b[i]].append(a[i])
print(counter)

Solution (Python):
import sys
import math
import collections
import itertools
import array
import inspect
import copy


sys.setrecursionlimit(10000)


def chkprint(*args):
    names = {id(v):k for k,v in inspect.currentframe().f_back.f_locals.items()}
    print(', '.join(names.get(id(arg),'???')+' = '+repr(arg) for arg in args))


def to_bin(x):
    return bin(x)[2:]


def dim2input(N):
    li = []
    for _ in range(N):
        li.append(input().split())
    return li



dp = None

def A_is_connected(A, edge, n_V):
    A[edge[0]][edge[1]] = False
    A[edge[1]][edge[0]] = False

    queue = [1]
    reached = [1]

    while len(queue) != 0:
        new_queue = []
        for q in queue:
            for i, is_connected in enumerate(A[q]):
                if is_connected and i not in reached:
                    new_queue.append(i)
                    reached.append(i)

        queue = new_queue

    return len(reached) == n_V


def main():
    n_V, n_E = list(map(int, input().split()))

    A = []
    for i in range(n_V+1):
        A.append([])
        for j in range(n_V+1):
            A[i].append(False)

    edges = []
    for _ in range(n_E):
        edges.append(list(map(int, input().split())))

    for edge in edges:
        A[edge[0]][edge[1]] = True
        A[edge[1]][edge[0]] = True

    n_bridge = 0

    for edge in edges:
        origin_A = copy.deepcopy(A)
        if not A_is_connected(A, edge, n_V):
            n_bridge += 1
        A = origin_A

    print(n_bridge)


main()

Solution (Python):
def DFS(v):
  if(already[v]==0):
    already[v]=1
    for i in range(n):
      if(con[v][i]==1):
        if(already[i]==0):
          DFS(i)


n,m=map(int,input().split())
INF=10**15
a=[-1for i in range(m)]
b=[-1for i in range(m)]
count=0
for i in range(m):
  a[i],b[i]=map(int,input().split())
  a[i]-=1
  b[i]-=1
for i in range(m):
  con=[[0 for n in range(n)]for j in range(n)]
  for j in range(n):con[j][j]=1
  already=[0 for i in range(n)]
  for j in range(m):
    if(i!=j):
      con[a[j]][b[j]]=1
      con[b[j]][a[j]]=1

  DFS(0)
  if(0 in already):count+=1
print(count)

Solution (Python):
def dfs(array, visited, next):
    if visited[next] is not True and len(array[next]) != 0:
        visited[next] = True
        for next_node in array[next]:
            visited = dfs(array, visited, next_node)
    else:
        return visited
    return visited


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

cnt = 0
for _ in edge_array:
    remove_edge = edge_array[0]
    edge_array.remove(remove_edge)
    node_array = [[] for x in range(n + 1)]
    
    for edge in edge_array:
        node_array[edge[0]].append(edge[1])
        node_array[edge[1]].append(edge[0])
        visited = [False]*(n+1)
    res = dfs(node_array, visited, 1)
    if res.count(False) != 1:
        cnt += 1
    edge_array.append(remove_edge)

print(cnt)

Solution (Python):
n,m = map(int,input().split())
pair=[list(map(lambda x:int(x)-1,input().split())) for _ in range(m)]
graph=[[n]*n for i in range(n)]

def dfs(v):
    if visited[v]:
        return
    visited[v]=True
    for j in [j for j,v2 in enumerate(graph[v]) if v2 == 1]:
        dfs(j)

ans = 0

for p in pair:
    graph[p[0]][p[1]] = graph[p[1]][p[0]] = 1
    
for i in range(m):
    visited=[False]*n
    x,y = pair[i]
    graph[x][y] = graph[y][x] = 0    
    dfs(0)
    
    if not all(visited):
        ans += 1
        
    graph[x][y] = graph[y][x] = 1     
    
print(ans)

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

pair=[list(map(lambda x:int(x)-1,input().split())) for _ in range(M)]
graph=[[0]*N for _ in range(N)] 


for p in pair:
	graph[p[0]][p[1]]= graph[p[1]][p[0]]=1
	
def DFS(v):
	if visited[v]:
		return 
	visited[v]=True
	for j in [j for j,v2 in enumerate(graph[v]) if v2==1]:
		DFS(j)
		
res = 0

for i in range(M):
	visited=[False for _ in range(N)] 
	x,y=pair[i]
	graph[x][y]=graph[y][x]=0 
	DFS(0)

	
	if not all(visited):
		res+=1
	
	graph[x][y]=graph[y][x]=1

print(res)

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

pair=[list(map(lambda x:int(x)-1,input().split())) for _ in range(M)]
graph=[[0]*N for _ in range(N)] 


for p in pair:
	graph[p[0]][p[1]]= graph[p[1]][p[0]]=1
	
def DFS(v):
	if visited[v]:
		return 
	visited[v]=True
	for j in [j for j,v2 in enumerate(graph[v]) if v2==1]:
		DFS(j)
		
res = 0

for i in range(M):
	visited=[False for _ in range(N)] 
	x,y=pair[i]
	graph[x][y]=graph[y][x]=0 
	DFS(0 if i>0 else 1)
	
	if not all(visited):
		res+=1
	
	graph[x][y]=graph[y][x]=1

print(res)

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

print(sum(dfs(b, a, b, set()) == 0 for a, b in ab))

Solution (Python):

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

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


def connected(E, n):
    V = {i: False for i in range(1, n+1)}
    V[1] = True
    
    queue = []
    queue.append(1)
    while queue:
        i = queue.pop()
        for (a, b) in E:
            if i == a and not V[b]:
                V[b] = True
                queue.append(b)
            if b == i and not V[a]:
                V[a] = True
                queue.append(a)

    for i, b in V.items():
        if not b:
            return False
    return True

def rest(E, e):
    xs = []
    for f in E:
        if f != e:
            xs.append(f)
    return xs


count = 0
for e in ab:
    F = rest(ab, e)
    if not connected(F, n):
        count += 1
print(count)

Solution (Python):

from sys import setrecursionlimit
setrecursionlimit(100000)
 
def inpl(): return tuple(map(int, input().split()))
 
N, M = inpl()
graph = [[] for k in range(N)]
 
for _ in range(M):
    s, t = inpl()
    s, t = s-1, t-1
    graph[s].append(t)
    graph[t].append(s)
 
prenum = [-1] * N
lowest = [float("inf")] * N
found = [False] * N
parent = [-1] * N
 
result = set()
bridges = set()
root = 0

def DFS(i, cur, prev):
    global root
    prenum[i] = cur
    lowest[i] = cur
    found[i] = True
    parent[i] = prev 
    for p in graph[i]:
        if found[p]:
            if p != prev:
                lowest[i] = min(lowest[i], prenum[p])
        else:
            cur = DFS(p, cur+1, i)
            lowest[i] = min(lowest[i], lowest[p])
    if prenum[prev] <= lowest[i]:
        result.add(prev)    
     
    return cur
DFS(0, 1, -1)
 
if parent.count(0) <= 2:
    result = result.difference([0])

bridges = set()

for i in range(1, N):
    p = parent[i]
    if prenum[p] < lowest[i]:
        if p > i:
            p, i = i, p
        bridges.add((p, i))

print(len(bridges))

Solution (Python):

import numpy as np
connected = 0

def dfs(graph, start, v, visited=None):
    if(visited==None):  visited = []
    visited.append(start)    
    if(len(visited)==v):
        global connected
        connected += 1
        return
    for Next in graph[start]:  
        if ( Next in visited ):  continue
        dfs(graph, Next, v, visited)
    return


v, e = map(int, input().split())
graph = np.zeros((e,2)).astype('uint16')

for i in range(e):
    graph[i] = list(map(int, input().split()))

lw = [[] for i in range(v)]
for path in graph:
    lw[path[0]-1].append(path[1]-1)
    lw[path[1]-1].append(path[0]-1)

for path in graph:
    lw[path[0]-1].remove(path[1]-1)
    lw[path[1]-1].remove(path[0]-1)
    dfs(lw,0,v)
    lw[path[0]-1].append(path[1]-1)
    lw[path[1]-1].append(path[0]-1)
print(e-connected)

Solution (Python):
line = input().split(" ")
N = int(line[0])
M = int(line[1])

g = {}
E = []
for _ in range(M):
    line = input().split(" ")
    a = line[0]
    b = line[1]
    E.append((a,b))
    if not a in g:
        g[a] = []
    g[a].append(b)

    if not b in g:
        g[b] = []
    g[b].append(a)

def judge(a, b):
    flags = {}
    for v in g:
        flags[v] = False
    q = [a]
    flags[a] = True
    while len(q)>0:
        v = q.pop(0)
        for u in g[v]:
            if (v==a and u==b) or (v==b and u==a):
                continue
            elif not flags[u]:
                flags[u] = True
                q.append(u)
    ret = True
    for v in flags:
        ret = ret and flags[v]

    return not ret

cnt = 0
for e in E:
    if judge(e[0],e[1]):
        cnt += 1

print(cnt)

Solution (Python):
from copy import deepcopy

N,M  = [int(i) for i in input().split()]
ab   = [[int(i)-1 for i in input().split()] for j in range(M)]
edge = [[] for i in range(N)]
ans  = 0

for i in range(M):
        edge[ab[i][0]].append(ab[i][1])
        edge[ab[i][1]].append(ab[i][0])

def paint(tmpEdge):
        used=[False for i in range(N)]
        stack=[0]
        used[0]=True
        while len(stack)>0:
                now=stack[-1]
                stack.pop(-1)
                for nextP in tmpEdge[now]:
                        if used[nextP]==False:
                                used[nextP]=True
                                stack.append(nextP)

        
        if False in used:
                return True
        else:
                return False

for i in range(M):
        tmpEdge=deepcopy(edge)
        tmpEdge[ab[i][0]].remove(ab[i][1])
        tmpEdge[ab[i][1]].remove(ab[i][0])
        if paint(tmpEdge):
                ans+=1
print(ans)

Solution (Python):
N, M = map(int, raw_input().split())
E = [map(lambda v: int(v)-1, raw_input().split()) for i in range(M)]
ans = 0
for k in range(M):
    used = [False] * N
    used[0] = True
    que = [0]
    while que != []:
        s = que.pop(0)
        for i in range(M):
            if i != k:
                a, b = E[i]
                if (s == a) and not used[b]:
                    used[b] = True
                    que.append(b)
                elif (s == b) and not used[a]:
                    used[a] = True
                    que.append(a)
    ans += sum(used) < N
print ans

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

dotlist = [[] for i in range(N)]
sidlist = []
count = 0 

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

def check(anum,bnum,cnum):
    donedot[cnum-1] = True
    for i in dotlist[cnum - 1]: 
        if (anum == cnum and i == bnum) or (bnum == cnum and i == anum):
            pass
        elif donedot[i - 1] == False:
            check(anum,bnum,i)

donedot = None

for m in range(M):
    donedot = [False for i in range(N)]
    a,b = sidlist[m]
    check(a,b,1)
    TorF = True
    for i in donedot:
        TorF  = TorF and i
    if  not TorF:
        count += 1

print(count)

Solution (Python):
a,b=[int(i) for i in input().split()]

n=[[] for i in range(a)]

e=[]

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


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

for i,j in e:
  s=[]

  loopn(j,i,j)
  if i not in s:
    x +=1 
print(x)

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

L = []

for _ in range(M):
    a, b = map(int, input().split())
    L.append((a, b))


def f(l):
    passed = {i:False for i in range(1, N+1)}
    q = collections.deque()
    q.append(1)

    while len(q) > 0:
        now = q.popleft()
        nodes = l[now]
        for n in nodes:
            if not passed[n]:
                passed[n] = True
                q.append(n)

    for v in passed.values():
        if not v:
            return False

    return True

count = 0

for i in range(M):
    l = {j:[] for j in range(1,N+1)}
    for j in range(M):
        if j != i:
            l[L[j][0]].append(L[j][1])
            l[L[j][1]].append(L[j][0])
    if not f(l):
        count += 1

print(count)

Solution (Python):
N,M=map(int,input().split())
es = [ tuple(map(int,input().split())) for _ in range(M) ]
ans = 0

data = [0] * (N+1)
def root(i):
  if data[i] < 0:
    return i
  data[i] = root(data[i])
  return data[i]

def link(a, b):
  a = root(a)
  b = root(b)
  if a != b:
    if -data[a] > -data[b]:
      data[a] += data[b]
      data[b] = a
    else:
      data[b] += data[a]
      data[a] = b

for i in range(M):
  for x in range(N+1):
    data[x] = -1
  for j in range(M):
    if i == j: continue
    link( es[j][0], es[j][1])
  if root( es[i][0]) != root( es[i][1]):
    ans += 1
print(ans)

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

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

low=[-1]*N
pre=[-1]*N

def dfs(u,count,p):
	pre[u] = count;
	low[u] = pre[u];
	for v in edges[u]:
		if pre[v] == -1:
			low[u] = min(low[u], dfs(v,count+1,u))
		else:
			if v == p:
				continue
			low[u] = min(low[u], low[v])
	return low[u]

count=0
dfs(0,count,-1)
res=0

for i in range(1,N):

	res += (1 if low[i] == pre[i] else 0)

print(res)

Solution (Python):
inp = input().split(" ")
num_vertex = int(inp[0])
num_edge = int(inp[1])

visited = []
def _dfs(graph, start, end):
	neighbors = graph[start]
	for i in neighbors:
		if i == end:
			return True
		elif i not in visited:
			visited.append(i)
			found = _dfs(graph, i, end)
			if found:
				return found
	return False

def dfs(graph, start, end):
	global visited
	visited = []
	return _dfs(graph, start, end)

vertices = {}
edges = []
for i in range(num_vertex):
	vertices[i+1] = []

for i in range(num_edge):
	inp = input().split(" ")
	edge = list(map(int, inp))
	vertices[edge[0]].append(edge[1])
	vertices[edge[1]].append(edge[0])
	edges.append(edge)

bridges = 0
for edge in edges:
	v = vertices.copy()
	e0 = v[edge[0]].copy()
	e1 = v[edge[1]].copy()
	e0.remove(edge[1])
	e1.remove(edge[0])
	v[edge[0]] = e0
	v[edge[1]] = e1
	if not dfs(v, edge[0], edge[1]):
		bridges += 1
print(bridges)

Solution (Python):
from collections import deque
def is_bridge(start, nodes, edge_tuple, n):
    seen = set()
    queue = deque()

    queue.append(start)
    seen.add(start)
    while len(queue) > 0:
        head = queue.popleft()
        for child in nodes[head]:
            if child not in seen and not (  (child == edge_tuple[0] and head == edge_tuple[1]) or   (child == edge_tuple[1] and head == edge_tuple[0])):
                seen.add(child)
                queue.append(child)


    return len(seen) != n



line_one = raw_input().split()
n = int(line_one[0])
m = int(line_one[1])

nodes = {}
edges = []
rand_start = None

for i in range(m):
    line = raw_input().split()
    edge = (int(line[0]), int(line[1]))
    if rand_start is None:
        rand_start = edge[0]

    if edge[0] not in nodes:
        nodes[edge[0]] = []
    if edge[1] not in nodes:
        nodes[edge[1]] = []

    nodes[edge[0]].append(edge[1])
    nodes[edge[1]].append(edge[0])

    edges.append(edge)
count = 0
for edge in edges:
    if is_bridge(rand_start, nodes, edge, n):
        count += 1

print count

Solution (Python):
def f(a, b, nodes, visited):
    if (a in visited):
        return False
    if (a == b):
        return True
    visited.append(a)
    for e in nodes[a]:
        if (f(e, b, nodes, visited)):
            return True
    return False


def main():
    n, m = [int(x) for x in input().split(' ')]
    nodes = {}
    edges = []
    for _ in range(m):
        a, b = [int(x) for x in input().split(' ')]
        if (a in nodes):
            nodes[a].append(b)
        else:
            nodes[a] = [b]
        if (b in nodes):
            nodes[b].append(a)
        else:
            nodes[b] = [a]
        edges.append((a, b))
    ans = 0
    for a, b in edges:
        nodes[a] = [x for x in nodes[a] if x != b]
        nodes[b] = [x for x in nodes[b] if x != a]
        if (not f(a, b, nodes, [])):
            ans += 1
        nodes[a].append(b)
        nodes[b].append(a)
    print(ans)


main()

Solution (Python):
N, M = [int(a) for a in input().split()]
adj = [[False] * N for _ in range(N)]
edgelist = []
for i in range(M):
    a, b = [int(a) for a in input().split()]
    a-=1
    b-=1
    adj[a][b] = True
    adj[b][a] = True
    edgelist.append((a,b))

bridges = 0
for a,b in edgelist:
    adj[a][b] = False
    adj[b][a] = False

    marked = [False] * N
    stk = [a]
    while stk:
        x = stk.pop()
        marked[x] = True
        for i in range(N):
            if adj[x][i] and not marked[i]:
                stk.append(i)
    if not marked[b]:
        bridges += 1

    adj[a][b] = True
    adj[b][a] = True

print(bridges)

Solution (Python):
n, m = map(int, input().split())
a = [[False]*n for i in range(n)]
hen_m = []
for i in range(m):
    x1, x2 = map(int, input().split())
    x1 -= 1
    x2 -= 1
    hen_m.append([x1, x2])
    a[x1][x2] = True
    a[x2][x1] = True
for i in range(n):
    a[i][i] = True


def warshall(n, c):
    for i in range(n):
        for j in range(n):
            for k in range(n):
                c[j][k] = c[j][k] or (c[j][i] and c[i][k])

ans = 0

for i in range(m):
    b = [i[::] for i in a]
    x1 , x2 = hen_m[i]
    b[x1][x2] = False
    b[x2][x1] = False
    warshall(n, b)
    flag = 0
    for j in range(n - 1):
        for k in range(j + 1,n):
            if not b[j][k]:
                flag = 1
                break
        if flag == 1:
            break
    
    ans += flag
print(ans)

Solution (Python):
import sys
from copy import deepcopy



class Node(object):

    def __init__(self, value):
        self.value = value
        self.visited = False
        self.adjacencies = []

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return str(self.value)

    def add_adjaency(self, node):
        if isinstance(node, Node):
            self.adjacencies.append(node)
        else:
            raise TypeError('Type "Node" expected, but received {0}'.format(type(node)))

    def remove_adjacency(self, node):
        self.adjacencies.remove(node)

    def is_visited(self):
        return self.visited

    def mark_as_visited(self):
        self.visited = True

    def clear_history(self):
        self.visited = False


class Graph(object):

    def __init__(self):
        self.nodes = []
        self.root = None
        self.search_result = None  

    def __str__(self):
        return self.nodes

    def mark_as_root(self, node):
        self.root = node

    def add_node(self, node):
        if isinstance(node, Node):
            self.nodes.append(node)
            if self.root is None:
                self.mark_as_root(node)
        else:
            raise TypeError('Type "Node" expected, but received {0}'.format(type(node)))

    @staticmethod
    def add_uni_link(from_node, to_node):  
        from_node.add_adjaency(to_node)

    @staticmethod
    def remove_uni_link(from_node, to_node):  
        from_node.remove_adjacency(to_node)

    @staticmethod
    def add_bi_link(node1, node2):  
        node1.add_adjaency(node2)
        node2.add_adjaency(node1)

    @staticmethod
    def remove_bi_link(node1, node2):  
        node1.remove_adjacency(node2)
        node2.remove_adjacency(node1)

    def clear_history(self):
        for node in self.nodes:
            node.clear_history()

    def dfs(self, value, start_node=None):
        """Depth First Search
        :returns reference of node where the value matches attribute value.
        """
        self.search_result = None
        self.clear_history()

        if start_node is None:
            start_node = self.root

        self._dfs(start_node, value)

    def _dfs(self, start_node, value):
        self._visit(node=start_node, search_value=value)

        for adjacency in start_node.adjacencies:
            if not adjacency.is_visited():
                self._dfs(start_node=adjacency, value=value)
        return

    def _visit(self, node, search_value):
        node.mark_as_visited()
        if node.value == search_value:
            self.search_result = node
        else:
            return


def main():

    
    a, b, N, M = _input_args()  

    
    result = _main(a, b, N, M)

    
    _output_result(result)


def _main(a, b, N, M):
    """Write Main Logic here for the contest.

    :param args: arguments
    :type args: list
    :return: result
    :rtype: depends on your logic.
    """

    bridges = 0  
    offset = -1  

    for i in range(M):
        
        graph = Graph()

        
        for n in range(N):
            graph.add_node(Node(value=n + 1))

        
        a_temp = deepcopy(a)
        b_temp = deepcopy(b)

        del a_temp[i]
        del b_temp[i]

        
        for n1_index, n2_index in zip(a_temp, b_temp):
            graph.add_bi_link(graph.nodes[n1_index + offset], graph.nodes[n2_index + offset])

        
        for nd in range(N):
            graph.dfs(value=nd+1)
            if graph.search_result is None:
                bridges += 1
                break

    return bridges


def _input_args():

    arguments = _get_args_from_multiple_lines(end_of_lines_char=[''], limit=10000000)

    a = []
    b = []
    N, M = map(int, arguments[0].split())
    pairs = arguments[1:]

    for i in range(0, len(pairs)):
        ai, bi = map(int, pairs[i].split())
        a.append(ai)
        b.append(bi)

    return a, b, N, M


def _input():
    
    return input()  


def _get_args_from_multiple_lines(end_of_lines_char=[''], limit=10000000):
    """Get arguments from multiple lines standard input.

    :param end_of_lines_char: Strings that indicate the end of lines.
    :type end_of_lines_char: list of str
    :param limit: If a number of the input line are certain, you can use this param to close prompt immediately.
    :type limit: int
    :return: args
    :rtype list of str
    """
    args = []
    for i in range(limit):
        try:
            arg = _input()
            if arg in end_of_lines_char:
                break
            args.append(arg)
        except EOFError:  
            break
    return args


def _output_result(result):
    print('{}'.format(str(result)))  


if __name__ == '__main__':
    main()

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

E = [[] for i in range(N)]

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

visited = []


def search(pos):
    for n_pos in E[pos]:
        if n_pos not in visited:
            visited.append(n_pos)
            search(n_pos)

count = 0
for i in range(M):
    visited = []
    E = [[] for i in range(N)]
    for j in range(M):
        if j == i:
            continue
        E[ab[j][0]].append(ab[j][1])
        E[ab[j][1]].append(ab[j][0])
    search(0)
    if len(visited) < N:
        count += 1

print(count)

Solution (Python):
import collections


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


def is_connected_graph(graph):  
    """グラフが連結か判定する。

    Args:
        - graph: 隣接リスト形式
    """
    graph_size = len(graph)
    if graph_size == 0:
        return True
    connected = [False] * graph_size
    dq = collections.deque([0])  
    connected[0] = True
    while dq:
        node = dq.popleft()
        for adjacent_node in graph[node]:
            if connected[adjacent_node]:
                continue
            connected[adjacent_node] = True
            dq.append(adjacent_node)
    return all(connected)


def enumerate_bridge(graph):  
    """グラフの橋を列挙する。

    Args:
        - graph: 隣接リスト形式

    Returns:
        - 橋の配列。ソートしていない。
    """
    graph_size = len(graph)
    if graph_size == 0:
        return True

    bridges = []

    visited = [False] * graph_size
    order = [-1] * graph_size
    lowlink = [float('inf')] * graph_size
    k = 0

    def __dfs(node, pre_node):
        nonlocal k
        visited[node] = True

        order[node] = k
        lowlink[node] = order[node]
        k += 1

        ct = 0

        for next_node in graph[node]:
            if not visited[next_node]:
                ct += 1
                __dfs(next_node, node)
                lowlink[node] = min(lowlink[node], lowlink[next_node])
                if order[node] < lowlink[next_node]:
                    bridges.append(
                        (min(node, next_node), max(node, next_node)))
            elif next_node != pre_node:
                lowlink[node] = min(lowlink[node], order[next_node])

    for i in range(graph_size):
        if not visited[i]:
            __dfs(i, -1)
    return bridges


print(len(enumerate_bridge(graph)))

Solution (Python):
def BFS(n,path):
  """頂点数nと隣接リストpathを与え、連結かどうかをチェックする"""
  check=[0]*n
  check[0]=1
  Que=[0]
  while Que:
    u=Que.pop(-1)
    for v in path[u]:
      if check[v]==0:
        check[v]=1
        Que.append(v)
  if check!=[1]*n: return 1
  else: return 0

N,M=map(int,input().split())
A=[]
B=[]
for i in range(M):
  a,b=map(int,input().split())
  A+=[a-1]
  B+=[b-1]
ans=0
for i in range(M):
  edges=[[] for i in range(N)]
  for j in range(M):
    if j!=i:
      edges[A[j]]+=[B[j]]
      edges[B[j]]+=[A[j]]
  ans+=BFS(N,edges)
print(ans)

Solution (Python):

N,M = [int(i) for i in input().split()]
Nodes = []
Mlist = []
count = 0
for i in range(N):
    Mlist.append(1)
for i in range(M):
    Nodes.append(list(map(int, input().split())))


def search(x):
    Mlist2[x-1] = 0
    for i in range(len(Nodes2)):
        if x in Nodes2[i]:
            if Nodes2[i].index(x) == 0:
                if Mlist2[Nodes2[i][1]-1] != 0:
                    search(Nodes2[i][1])
                else: continue
            if Nodes2[i].index(x) == 1:
                if Mlist2[Nodes2[i][0]-1] != 0:
                    search(Nodes2[i][0])
                else: continue
        else: continue
    
    return(Mlist2)

def cout(x):
    answer = 1
    for i in range(len(x)):
        if x[i] == 0:
            continue
        else:
            answer = 0
            break
    if answer == 1:
        return 1
    if answer == 0:
        return 0

for i in range(M):
    
    Nodes2 = Nodes[:]
    Mlist2 = Mlist[:]
    del Nodes2[i]
    ans = cout(search(1))
    if ans == 0:
        count += 1
print(count)

Solution (Python):

N,M = [int(i) for i in input().split()]
Nodes = []
Mlist = []
count = 0
for i in range(N):
    Mlist.append(1)
for i in range(M):
    Nodes.append(list(map(int, input().split())))


def search(x):
    Mlist2[x-1] = 0
    answer = 1
    for i in range(len(Nodes2)):
        if x in Nodes2[i]:
            if Nodes2[i].index(x) == 0:
                if Mlist2[Nodes2[i][1]-1] != 0:
                    search(Nodes2[i][1])
                else: continue
            if Nodes2[i].index(x) == 1:
                if Mlist2[Nodes2[i][0]-1] != 0:
                    search(Nodes2[i][0])
                else: continue
        else: continue
    
    for i in range(len(Mlist2)):
        if Mlist2[i] == 0:
            continue
        else:
            answer = 0
            break
    if answer == 1:
        return 1
    if answer == 0:
        return 0

for i in range(M):
    
    Nodes2 = Nodes[:]
    Mlist2 = Mlist[:]
    del Nodes2[i]
    ans = search(1)
    if ans == 0:
        count += 1
print(count)