Read problem statements in [Hindi], [Bengali], [Mandarin Chinese], [Russian], and [Vietnamese] as well.

Chef has always dreamed of becoming an employee of the "Hack and Manipulate Group". Their work is simple ― attacking networks. They gave Chef the following task to assess his programming skills, but Chef is too busy cooking "Vegetable Gourmet". Can you solve the task for him?

A network consists of $N$ nodes (numbered $1$ through $N$) and $M$ bidirectional connections between pairs of these nodes. A *robust network* is a network that contains a cycle. Shutting down a node means removing that node (and all direct connections it is part of) from the network.

You may shut down at most one node. If the network was robust before it was shut down and is not robust afterwards, this node is called the *point of failure*.

Is the initial network robust? If it is robust, does it have a point of failure? If it does, find the point of failure with the smallest number.

------  Input ------
The first line of the input contains a single integer $T$ denoting the number of test cases. The description of $T$ test cases follows.
The first line of each test case contains two space-separated integers $N$ and $M$.
Each of the following $M$ lines contains two space-separated integers $u$ and $v$ denoting that nodes $u$ and $v$ are directly connected.

------  Output ------
For each test case, print a single line containing one integer ― the smallest number of a point of failure, or $-1$ if the network does not have a point of failure.

------  Constraints ------
$1 ≤ T ≤ 10$
$1 ≤ N ≤ 10^{5}$
$0 ≤ M ≤ 10^{5}$
$1 ≤ u, v ≤ N$

------  Subtasks ------
Subtask #1 (10 points):
$N ≤ 100$
$N - 1 ≤ M ≤ N + 1$
the given graph is connected

Subtask #2 (10 points): $1 ≤ N ≤ 100$

Subtask #3 (30 points): $1 ≤ N ≤ 1,000$

Subtask #4 (50 points): original constraints

----- Sample Input 1 ------ 
5

5 5

5 1

5 2

1 2

2 3

2 4

5 6

4 5

4 1

4 2

4 3

5 1

5 2

5 5

3 4

3 5

3 1

3 2

4 2

4 1

3 4

6 6

1 2

2 3

3 1

4 5

5 6

6 4
----- Sample Output 1 ------ 
1

4

2

-1

-1

Difficulty: VERY_HARD
Tags: Tree algorithms

Graph algorithms

Data structures

Graph traversal
Skill types: Data structures

Starter code:

Solutions:
from collections import defaultdict

class UndirectedGraph:

	def __init__(self, node_num):
		self.node_num = node_num
		self.graph = defaultdict(list)

	def add_edge(self, v, w):
		self.graph[v].append(w)
		self.graph[w].append(v)

	def _find(self, v, visited, deleted):
		stack = [v]
		parent = defaultdict(int)
		while stack:
			v = stack.pop()
			for next_v in self.graph[v]:
				if next_v == parent[v]:
					continue
				if visited[next_v]:
					path = [v]
					while next_v != v:
						v = parent[v]
						path.append(v)
					return path
				if next_v not in deleted:
					parent[next_v] = v
					stack.append(next_v)
			visited[v] = True
		return None

	def find_cycle(self, del_nodes):
		visited = [False] * (self.node_num + 1)
		deleted = set(del_nodes)
		for i in self.graph:
			if not visited[i] and i not in deleted:
				cycle = self._find(i, visited, deleted)
				if cycle:
					return cycle
		return []
try:
	test_num = int(input())

	def get_input():
		return list(map(int, input().split()))
	for _ in range(test_num):
		(n, m) = get_input()
		edges = [get_input() for _ in range(m)]
		g = UndirectedGraph(n)
		for (i, j) in edges:
			g.add_edge(i, j)
		(cycle, fail_node) = (g.find_cycle([]), -1)
		if cycle and (not g.find_cycle(cycle)):
			cycle.sort()
			for i in cycle:
				if not g.find_cycle([i]):
					fail_node = i
					break
		print(fail_node)
except EOFError:
	pass


from collections import defaultdict
II = lambda : [int(x) for x in input().split()]

def find_cycle(graph, start, visited, d_nodes):
	d_nodes = set(d_nodes)
	stack = [start]
	parent = defaultdict(int)
	while stack:
		state = stack.pop()
		for next_state in graph[state]:
			if next_state == parent[state]:
				continue
			if visited[next_state]:
				path = [state]
				while next_state != state:
					state = parent[state]
					path.append(state)
				return path
			if next_state not in d_nodes:
				parent[next_state] = state
				stack.append(next_state)
		visited[state] = True
	return None

def find_a_cycle(G, d_nodes):
	visited = defaultdict(bool)
	d_nodes = set(d_nodes)
	for node in G:
		if node not in visited and node not in d_nodes:
			cycle = find_cycle(G, node, visited, d_nodes)
			if cycle is not None:
				return cycle
	return []
T = int(input())
for _ in range(T):
	(N, E) = II()
	G = defaultdict(list)
	for _ in range(E):
		(a, b) = II()
		G[a].append(b)
		G[b].append(a)
	cycle = find_a_cycle(G, [])
	if not cycle:
		print(-1)
		continue
	if find_a_cycle(G, cycle):
		print(-1)
		continue
	f_node = -1
	cycle.sort()
	for node in cycle:
		new_cycle = find_a_cycle(G, [node])
		if not new_cycle:
			f_node = node
			break
	print(f_node)


from collections import defaultdict
import sys
sys.setrecursionlimit(100000)

class Graph:

	def __init__(self):
		self.graph = defaultdict(set)
		self._junctionDict = defaultdict(set)

	def addEdge(self, u, v):
		self.graph[u].add(v)
		self.graph[v].add(u)
		lu = len(self.graph[u])
		lv = len(self.graph[v])
		self._junctionDict[lu].add(u)
		self._junctionDict[lv].add(v)
		if lu > 1:
			self.discardFromJunction(lu - 1, u)
		if lv > 1:
			self.discardFromJunction(lv - 1, v)

	def discardFromJunction(self, k, v):
		self._junctionDict[k].discard(v)
		if len(self._junctionDict[k]) == 0:
			del self._junctionDict[k]

	def removeVertice(self, v):
		for vv in self.graph[v]:
			self.graph[vv].discard(v)
			lv = len(self.graph[vv])
			self.discardFromJunction(lv + 1, vv)
			if lv > 0:
				self._junctionDict[lv].add(vv)
			else:
				del self.graph[vv]
		ln = len(self.graph[v])
		del self.graph[v]
		self.discardFromJunction(ln, v)

	def removeAloneVertice(self, u):
		if len(self.graph[u]) == 1:
			v = self.graph[u].pop()
			self.graph[v].discard(u)
			del self.graph[u]
			self.discardFromJunction(1, u)
			lv = len(self.graph[v])
			self.discardFromJunction(lv + 1, v)
			if lv > 0:
				self._junctionDict[lv].add(v)
			else:
				del self.graph[v]
		elif len(self.graph[u]) == 0:
			del self.graph[u]

	def clean(self):
		while self._junctionDict[1]:
			self.removeAloneVertice(self._junctionDict[1].pop())
		del self._junctionDict[1]

	def check(self):
		fp = -1
		self.clean()
		if self._junctionDict.keys():
			mlen = max(self._junctionDict.keys())
			if mlen > 1:
				c_fp = min(self._junctionDict[mlen])
				self.removeVertice(c_fp)
				self.clean()
			if len(self.graph.keys()) == 0:
				fp = c_fp
		print(fp)
for _ in range(int(input())):
	(N, M) = map(int, input().split())
	graph = Graph()
	for _ in range(M):
		(u, v) = map(int, input().split())
		graph.addEdge(u, v)
	graph.check()


from collections import defaultdict
import sys
sys.setrecursionlimit(100000)

class Graph:

	def __init__(self, N):
		self.Explored = [False] * N
		self.N = N
		self.graph = defaultdict(set)
		self.failurePoints = None
		self.path = []
		self.explored = [-1] * N
		self.Halt = False
		self.minFailurePoint = -1
		self._junctionDict = defaultdict(set)

	def addEdge(self, u, v):
		self.graph[u].add(v)
		self.graph[v].add(u)
		lu = len(self.graph[u])
		lv = len(self.graph[v])
		self._junctionDict[lu].add(u)
		self._junctionDict[lv].add(v)
		if lu > 1:
			self.discardFromJunction(lu - 1, u)
		if lv > 1:
			self.discardFromJunction(lv - 1, v)

	def discardFromJunction(self, k, v):
		self._junctionDict[k].discard(v)
		if len(self._junctionDict[k]) == 0:
			del self._junctionDict[k]

	def removeVertice(self, v):
		for vv in self.graph[v]:
			self.graph[vv].discard(v)
			lv = len(self.graph[vv])
			self.discardFromJunction(lv + 1, vv)
			if lv > 0:
				self._junctionDict[lv].add(vv)
			else:
				del self.graph[vv]
		ln = len(self.graph[v])
		del self.graph[v]
		self.discardFromJunction(ln, v)

	def removeAloneVertice(self, u):
		if len(self.graph[u]) == 1:
			v = self.graph[u].pop()
			self.graph[v].discard(u)
			del self.graph[u]
			self.discardFromJunction(1, u)
			lv = len(self.graph[v])
			self.discardFromJunction(lv + 1, v)
			if lv > 0:
				self._junctionDict[lv].add(v)
			else:
				del self.graph[v]
		elif len(self.graph[u]) == 0:
			del self.graph[u]

	def clean(self):
		while self._junctionDict[1]:
			self.removeAloneVertice(self._junctionDict[1].pop())
		del self._junctionDict[1]

	def check(self):
		fp = -1
		self.clean()
		if self._junctionDict.keys():
			mlen = max(self._junctionDict.keys())
			if mlen > 1:
				c_fp = min(self._junctionDict[mlen])
				self.removeVertice(c_fp)
				self.clean()
			if len(self.graph.keys()) == 0:
				fp = c_fp
		print(fp)

	def _intersection(self, s1, s2):
		intersection = set([])
		for v in s1:
			if v in s2:
				if len(intersection) == 0:
					self.minFailurePoint = v
				elif self.minFailurePoint > v:
					self.minFailurePoint = v
				intersection.add(v)
		return intersection

	def addCyclePath(self, nv):
		path = self.path[self.explored[nv - 1]:]
		if self.failurePoints is None:
			self.failurePoints = set([])
			self.minFailurePoint = path[0]
			for v in path:
				self.failurePoints.add(v)
				if self.minFailurePoint > v:
					self.minFailurePoint = v
		else:
			if len(self.failurePoints) <= len(path):
				_path = set(path)
				self.failurePoints = self._intersection(self.failurePoints, _path)
			else:
				self.failurePoints = self._intersection(path, self.failurePoints)
			if len(self.failurePoints) == 0:
				self.Halt = True
				raise Exception('Not possible')

	def getCycle(self, v, parent):
		index = len(self.path)
		self.explored[v - 1] = index
		self.Explored[v - 1] = True
		if self.graph[v]:
			self.path.append(v)
		else:
			return
		for nv in self.graph[v]:
			if self.Halt:
				return
			if nv != parent:
				if self.explored[nv - 1] > -1:
					self.addCyclePath(nv)
					continue
				else:
					self.getCycle(nv, v)
		self.explored[v - 1] = -1
		self.path = self.path[:-1]
for _ in range(int(input())):
	(N, M) = map(int, input().split())
	graph = Graph(N)
	for _ in range(M):
		(u, v) = map(int, input().split())
		graph.addEdge(u, v)
	graph.check()