Vlad has $n$ friends, for each of whom he wants to buy one gift for the New Year.

There are $m$ shops in the city, in each of which he can buy a gift for any of his friends. If the $j$-th friend ($1 \le j \le n$) receives a gift bought in the shop with the number $i$ ($1 \le i \le m$), then the friend receives $p_{ij}$ units of joy. The rectangular table $p_{ij}$ is given in the input.

Vlad has time to visit at most $n-1$ shops (where $n$ is the number of friends). He chooses which shops he will visit and for which friends he will buy gifts in each of them.

Let the $j$-th friend receive $a_j$ units of joy from Vlad's gift. Let's find the value $\alpha=\min\{a_1, a_2, \dots, a_n\}$. Vlad's goal is to buy gifts so that the value of $\alpha$ is as large as possible. In other words, Vlad wants to maximize the minimum of the joys of his friends.

For example, let $m = 2$, $n = 2$. Let the joy from the gifts that we can buy in the first shop: $p_{11} = 1$, $p_{12}=2$, in the second shop: $p_{21} = 3$, $p_{22}=4$.

Then it is enough for Vlad to go only to the second shop and buy a gift for the first friend, bringing joy $3$, and for the second — bringing joy $4$. In this case, the value $\alpha$ will be equal to $\min\{3, 4\} = 3$

Help Vlad choose gifts for his friends so that the value of $\alpha$ is as high as possible. Please note that each friend must receive one gift. Vlad can visit at most $n-1$ shops (where $n$ is the number of friends). In the shop, he can buy any number of gifts.


-----Input-----

The first line of the input contains an integer $t$ ($1 \le t \le 10^4$) — the number of test cases in the input.

An empty line is written before each test case. Then there is a line containing integers $m$ and $n$ ($2 \le n$, $2 \le n \cdot m \le 10^5$) separated by a space — the number of shops and the number of friends, where $n \cdot m$ is the product of $n$ and $m$.

Then $m$ lines follow, each containing $n$ numbers. The number in the $i$-th row of the $j$-th column $p_{ij}$ ($1 \le p_{ij} \le 10^9$) is the joy of the product intended for friend number $j$ in shop number $i$.

It is guaranteed that the sum of the values $n \cdot m$ over all test cases in the test does not exceed $10^5$.


-----Output-----

Print $t$ lines, each line must contain the answer to the corresponding test case — the maximum possible value of $\alpha$, where $\alpha$ is the minimum of the joys from a gift for all of Vlad's friends.


-----Examples-----

Input
5

2 2
1 2
3 4

4 3
1 3 1
3 1 1
1 2 2
1 1 3

2 3
5 3 4
2 5 1

4 2
7 9
8 1
9 6
10 8

2 4
6 5 2 1
7 9 7 2
Output
3
2
4
8
2


-----Note-----

None

Difficulty: MEDIUM_HARD
Tags: Sorting

Greedy algorithms
Skill types: Sorting

Greedy algorithms

Starter code:

Solutions:
t = int(input())
while t:

	def fun(num, n, m, li):
		arr = [False] * m
		flag = 0
		for i in range(n):
			c = 0
			for j in range(m):
				if li[i][j] >= num:
					arr[j] = True
					c += 1
			if c > 1:
				flag = 1
		if not flag and m > 1:
			return False
		ans = True
		for i in arr:
			ans = ans and i
		return ans
	space = input()
	(n, m) = map(int, input().split())
	li = []
	for i in range(n):
		a = list(map(int, input().split()))
		li.append(a)
	low = 1
	high = 2
	while fun(high, n, m, li):
		high *= 2
	while high - low > 1:
		mid = (low + high) // 2
		if fun(mid, n, m, li):
			low = mid
		else:
			high = mid
	print(low)
	t -= 1


import math
result = []

def check(x, shops, friends):
	if min(map(max, friends)) < x:
		return False
	for shop in shops:
		status = ''
		for value in shop:
			if value >= x:
				status += 'x'
		if len(status) >= 2:
			return True
	return False

def binary_search(func, l, r, *args, **kwargs):
	if l == r:
		return l
	c = math.ceil((l + r) / 2)
	if check(c, *args, **kwargs):
		return binary_search(func, c, r, *args, **kwargs)
	else:
		return binary_search(func, l, c - 1, *args, **kwargs)
for _ in range(int(input())):
	input()
	(m, n) = list(map(int, input().split()))
	shops = [list(map(int, input().split())) for i in range(m)]
	friends = [[shops[i][j] for i in range(m)] for j in range(n)]
	answer = binary_search(check, 0, 10 ** 9, shops, friends)
	result.append(answer)
print('\n'.join(map(str, result)))


import io, os
from sys import stdin, stdout
for _ in range(int(stdin.readline())):
	xxx = stdin.readline()
	(n, m) = map(int, stdin.readline().split())
	ar = []
	for i in range(n):
		ar.append(list(map(int, stdin.readline().split())))
	a = [[] for i in range(m)]
	for i in range(m):
		for j in range(n):
			a[i].append([ar[j][i], j])
		a[i].sort()
	mx = 0
	for i in range(n):
		mx = max(mx, max(ar[i]))
	l = 1
	r = mx
	ans = 0
	while l <= r:
		mid = l + (r - l) // 2
		d = {}
		check = False
		check1 = False
		for i in range(m):
			for j in range(n):
				if a[i][j][0] >= mid:
					if a[i][j][1] not in d:
						d[a[i][j][1]] = True
					else:
						check = True
						break
			if a[i][-1][0] < mid:
				check1 = True
				break
		if check1 or not check:
			r = mid - 1
		else:
			ans = mid
			l = mid + 1
	print(ans)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	aux = input()
	(m, n) = map(int, input().split())
	mat = []
	for i in range(m):
		l = list(map(int, input().split()))
		mat.append(l)
	d = {}
	h = {}
	s = set()
	flag = 0
	cnt = 10 ** 18
	for i in range(n):
		som = -1
		c = {}
		for j in range(m):
			if mat[j][i] in c:
				c[mat[j][i]].append(j)
			else:
				c[mat[j][i]] = [j]
			if mat[j][i] > som:
				som = mat[j][i]
		d[i] = som
		h[i] = c[som]
		cnt = min(cnt, som)
		for x in h[i]:
			if x in s:
				flag = 1
				break
			s.add(x)
	if flag:
		print(cnt)
		continue
	ans = -1
	for i in range(m):
		o = mat[i]
		o.sort()
		ans = max(ans, min(cnt, o[-2]))
	print(ans)


import math, sys
input = sys.stdin.readline
S = lambda : input().rstrip()
I = lambda : int(S())
M = lambda : map(int, S().split())
L = lambda : list(M())
mod1 = 1000000007
mod2 = 998244353
for _ in range(I()):
	S()
	(m, n) = M()
	l = []
	ans = 0
	for i in range(m):
		l.append(L())
		ans = max(ans, sorted(l[-1])[-2])
	for i in range(n):
		a = 0
		for j in range(m):
			a = max(a, l[j][i])
		ans = min(ans, a)
	print(ans)


import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def new_years_problem(m, n, joy_by_shop):
	best_present_by_friend = [0] * n
	for i in range(m):
		for j in range(n):
			best_present_by_friend[j] = max(best_present_by_friend[j], joy_by_shop[i][j])
	best_present_with_min_joy = min(best_present_by_friend)
	optimal_joy = 0
	if n > m:
		return best_present_with_min_joy
	for i in range(m):
		joys = sorted(joy_by_shop[i], reverse=True)
		optimal_joy = max(optimal_joy, min(best_present_with_min_joy, joys[1]))
	return optimal_joy
for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	joy_by_shop = [None] * m
	for i in range(m):
		joy_by_shop[i] = list(map(int, input().split()))
	sys.stdout.write(f'{new_years_problem(m, n, joy_by_shop)}\n')


from itertools import permutations as per
from math import factorial as fact
from difflib import SequenceMatcher
import bisect
t = int(input())
for _ in range(t):
	input()
	(m, n) = map(int, input().split())
	a = []
	for i in range(m):
		a.append([int(i) for i in input().split()])
	(sm, idx) = (-1, -1)
	for v in a:
		if v[0] > v[1]:
			(smx, mx) = (1, 0)
		else:
			(smx, mx) = (0, 1)
		for i in range(2, n):
			if v[i] > v[mx]:
				(smx, mx) = (mx, i)
			elif v[i] > v[smx]:
				smx = i
		if v[smx] > sm:
			(sm, idx) = (v[smx], smx)
	ans = sm
	for i in range(n):
		if i != idx:
			t = 0
			for j in range(m):
				t = max(t, a[j][i])
			ans = min(ans, t)
	print(ans)


def check(x, mat, n, m):
	flag = False
	pair = [False] * m
	for i in range(n):
		c = 0
		for j in range(m):
			if mat[i][j] >= x:
				pair[j] = True
				c += 1
		if c > 1:
			flag = True
	if not flag and m > 1:
		return False
	ans = sum(pair)
	if ans == m:
		return True
	return False
import sys

def solve():
	for t in range(1):
		s = input()
		(n, m) = map(int, input().split())
		arr = []
		mx = sys.maxsize * -1
		for i in range(n):
			a = list(map(int, input().split()))
			mx = max(mx, max(a))
			arr.append(a)
		start = 1
		end = mx
		ans = None
		while start <= end:
			mid = (start + end) // 2
			if check(mid, arr, n, m):
				ans = mid
				start = mid + 1
			else:
				end = mid - 1
		print(ans)
for _ in range(int(input())):
	solve()


import sys
import math
from collections import deque, Counter
from sys import stdin
int1 = lambda x: int(x) - 1
stinput = lambda : stdin.readline()[:-1]
ii = lambda : int(stinput())
mi = lambda : map(int, stdin.readline().split())
li = lambda : list(mi())
mi1 = lambda : map(int1, stdin.readline().split())
li1 = lambda : list(mi1())
mis = lambda : map(str, stdin.readline().split())
lis = lambda : list(mis())
from collections import defaultdict
import heapq
mod = 10 ** 9 + 7
Mod = 998244353
INF = 10 ** 18
ans = 0

def is_ok(arg):
	cnt = [0] * n
	f = False
	for i in range(m):
		tmp = 0
		for j in range(n):
			if a[i][j] >= arg:
				cnt[j] = 1
				tmp += 1
		if tmp >= 2:
			f = True
	if f and min(cnt) == 1:
		return True
	return False

def bisect(ng, ok):
	while abs(ok - ng) > 1:
		mid = (ok + ng) // 2
		if is_ok(mid):
			ok = mid
		else:
			ng = mid
	return ok
t = ii()
for _ in range(t):
	stinput()
	(m, n) = mi()
	a = [0] * m
	for i in range(m):
		a[i] = li()
	print(bisect(10 ** 9 + 1, -1))


from collections import defaultdict
import sys

def input():
	return sys.stdin.readline().rstrip()
DXY = [(0, -1), (1, 0), (0, 1), (-1, 0)]
mod = 998244353
inf = 1 << 64

def slv():
	_ = input()
	(m, n) = map(int, input().split())
	each_shop = [list(map(int, input().split())) for i in range(m)]

	def possible(X: int) -> bool:
		d = defaultdict(set)
		oks = set()
		for i in range(n):
			for j in range(m):
				if each_shop[j][i] >= X:
					d[j].add(i)
					oks.add(i)
		if len(oks) < n:
			return False
		for (k, v) in d.items():
			if len(v) > 1:
				return True
		return False
	ok = 0
	ng = 10 ** 9 + 1
	while ng - ok > 1:
		med = (ng + ok) // 2
		if possible(med):
			ok = med
		else:
			ng = med
	print(ok)
	return

def main():
	t = int(input())
	for i in range(t):
		slv()
	return 0
main()


import sys
import bisect
from bisect import bisect_left as lb
from bisect import bisect_right as rb
input_ = lambda : sys.stdin.readline().strip('\r\n')
from math import log
from math import gcd
from math import atan2, acos
from random import randint
sa = lambda : input_()
sb = lambda : int(input_())
sc = lambda : input_().split()
sd = lambda : list(map(int, input_().split()))
sflo = lambda : list(map(float, input_().split()))
se = lambda : float(input_())
sf = lambda : list(input_())
flsh = lambda : sys.stdout.flush()
sys.setrecursionlimit(3 * 10 ** 5)
mod = 10 ** 9 + 7
mod1 = 998244353
gp = []
cost = []
dp = []
mx = []
ans1 = []
ans2 = []
special = []
specnode = []
a = 0
kthpar = []

def dfs2(root, par):
	if par != -1:
		dp[root] = dp[par] + 1
	for i in range(1, 20):
		if kthpar[root][i - 1] != -1:
			kthpar[root][i] = kthpar[kthpar[root][i - 1]][i - 1]
	for child in gp[root]:
		if child == par:
			continue
		kthpar[child][0] = root
		dfs(child, root)
ans = 0
a = []
(n, k) = (0, 0)
b = []
vis = []
tot = 0
time = []
time1 = []
adj = []
mx = -1
eps = 1e-07
x = 0
pref = []
lvl = []
gp = []
ans = []
f = 0
w = []

def dfs(i, prod, rem, n):
	if rem == 0:
		while i < len(n):
			prod *= int(n[i])
			i += 1
		return prod
	if i == len(n):
		return prod
	mx = 0
	for j in range(9 - int(n[i])):
		mx = max(dfs(i + 1, (int(n[i]) + min(j, rem)) * prod, rem - min(j, rem), n), mx)
	return mx

def hnbhai(tc):
	sa()
	(m, n) = sd()
	mat = []
	d = {}
	mn = float('inf')
	for i in range(m):
		mat.append(sd())
		for j in range(n):
			d[j] = max(d.get(j, 0), mat[i][j])
	for i in d:
		mn = min(mn, d[i])
	if n > m:
		print(mn)
		return
	low = 1
	high = 10 ** 9
	ans = 0
	while low <= high:
		mid = (low + high) // 2
		tot = 0
		fl = 0
		for i in range(m):
			tot = 0
			for j in range(n):
				if mat[i][j] >= mid:
					tot += 1
			if tot >= 2:
				fl = 1
				break
		if fl == 1:
			low = mid + 1
			ans = mid
		else:
			high = mid - 1
	print(min(ans, mn))
for _ in range(sb()):
	hnbhai(_ + 1)


import sys

def solve(m, n, mat):
	mx = [0] * n
	mx2 = 0
	for row in mat:
		(n1, n2) = (0, 0)
		for (i, x) in enumerate(row):
			mx[i] = max(mx[i], x)
			if x > n1:
				(n1, n2) = (x, n1)
			elif x > n2:
				n2 = x
		mx2 = max(mx2, n2)
	if m < n:
		return min(mx)
	else:
		return min(min(mx), mx2)
t = int(sys.stdin.readline())
for _ in range(t):
	sys.stdin.readline()
	(m, n) = map(int, sys.stdin.readline().split())
	mat = []
	for _ in range(m):
		mat.append(list(map(int, sys.stdin.readline().split())))
	print(solve(m, n, mat))


def nypb(m, n, l2):
	ms = n - 1
	mv = [0] * n
	for i in range(m):
		cm = 0
		for j in range(n):
			mv[j] = max(mv[j], l2[i][j])
	ans = mv[0]
	for x in range(len(mv)):
		ans = min(ans, mv[x])
	if m <= n - 1:
		return ans
	cmm = 0
	mx1 = []
	mx2 = []
	for i in range(m):
		l5 = l2[i].copy()
		l5.sort()
		mx1.append(l5[-1])
		mx2.append(l5[-2])
	ans = min(ans, max(mx1), max(mx2))
	return ans
t = int(input())
ls = []
l = []
_ = str(input())
for x in range(t):
	s = str(input())
	ls.append(s)
	l1 = []
	for y in range(int(s.split(' ')[0])):
		s1 = str(input())
		l1.append(s1)
	l.append(l1)
	if x == t - 1:
		break
	_ = str(input())
la = []
for i in range(len(l)):
	(m, n) = (int(ls[i].split(' ')[0]), int(ls[i].split(' ')[1]))
	l2 = []
	for x in l[i]:
		y = x.split(' ')
		l3 = []
		for z in y:
			l3.append(int(z))
		l2.append(l3)
	ans = nypb(m, n, l2)
	la.append(ans)
for x in la:
	print(x)


def check(lst, val):
	visited = set()
	Flag = False
	ck = set()
	for i in range(n):
		can = False
		for j in range(m):
			if lst[j][i] >= val:
				can = True
				if j in visited:
					Flag = True
				visited.add(j)
		if not can:
			return False
	if Flag:
		return True
	return False

def solve(m, n, lst):
	lo = 1
	hi = 10 ** 9 + 1
	mid = (lo + hi) // 2
	ans = 0
	while lo <= hi:
		mid = (lo + hi) // 2
		if check(lst, mid):
			ans = mid
			lo = mid + 1
		else:
			hi = mid - 1
	print(ans)
t = int(input())
for i in range(t):
	x = input()
	(m, n) = map(int, input().split())
	lst = []
	for i in range(m):
		temp = list(map(int, input().split()))
		lst.append(temp)
	solve(m, n, lst)


from math import inf, gcd, log, log2, floor, ceil, sqrt
from collections import Counter, defaultdict
DIRS = [[1, 0], [0, 1], [0, -1], [-1, 0]]
MOD = 10 ** 9 + 7

def solve(A):
	(m, n) = (len(A), len(A[0]))

	def is_good(mini):
		has_pair = False
		column = [0 for x in range(n)]
		for i in range(m):
			row_cnt = 0
			for j in range(n):
				row_cnt += A[i][j] >= mini
				column[j] |= A[i][j] >= mini
			has_pair |= row_cnt >= 2
		return has_pair & (sum(column) == n)
	(l, r) = (0, 10 ** 9)
	while l < r:
		mid = l + (r - l + 1) // 2
		if is_good(mid):
			l = mid
		else:
			r = mid - 1
	return l
t = int(input())
for _ in range(t):
	input()
	A = []
	(m, n) = [int(x) for x in input().split(' ')]
	for _ in range(m):
		A.append([int(x) for x in input().split(' ')])
	print(solve(A))


import io, os
import sys
from sys import stdin
from bisect import bisect_left, bisect_right
from collections import defaultdict, deque, namedtuple
from heapq import heappush, heappop
from math import gcd, ceil, floor, factorial, sqrt
from itertools import combinations, permutations
input = sys.stdin.buffer.readline

def work():
	ans = 0
	return

def main_11():
	test = int(input())
	for idt in range(test):
		_ = input()
		(m, n) = map(int, input().split())
		(max1, max2) = ([0] * n, [0] * n)
		g = [[0] * n for _ in range(m)]
		for i in range(m):
			a = list(map(int, input().split()))
			for j in range(n):
				g[i][j] = a[j]
				if g[i][j] >= max1[j]:
					max2[j] = max1[j]
					max1[j] = g[i][j]
				elif g[i][j] >= max2[j]:
					max2[j] = g[i][j]
		ans = 0
		if n - 1 >= m:
			ans = min(max1)
			print(ans)
			continue
		s = [[[0] * 3 for _ in range(m)] for _ in range(n)]
		for i in range(n):
			for j in range(m):
				s[i][j][0] = g[j][i]
				s[i][j][1] = j
				s[i][j][2] = i
		for i in range(n):
			s[i].sort(reverse=True)
		cnt = [0] * m
		maxv = [0] * n
		for i in range(n):
			(x, idx, pid) = s[i][0]
			cnt[idx] += 1
			maxv[pid] = max(maxv[pid], x)
		count = 0
		for i in cnt:
			if i > 0:
				count += 1
		if count <= n - 1:
			print(min(maxv))
			continue
		ans = 0
		ops = defaultdict(list)
		for j in range(1, m):
			for i in range(n):
				(x, idx, pid) = s[i][j]
				cnt[idx] += 1
				ops[idx].append(pid)
				if cnt[idx] > 1:
					cnt[idx] -= 1
					t = float('inf')
					for k in ops[idx]:
						t = min(t, g[idx][k])
					t = min(min(maxv), t)
					ans = max(t, ans)
		print(ans)
	return

def main():
	test = int(input())
	for idt in range(test):
		_ = input()
		(m, n) = map(int, input().split())
		store_person = [[0] * n for _ in range(m)]
		for i in range(m):
			a = list(map(int, input().split()))
			for j in range(n):
				store_person[i][j] = a[j]
		person_store = [[] for _ in range(n)]
		for i in range(n):
			for j in range(m):
				person_store[i].append([store_person[j][i], j, i])
			person_store[i].sort(reverse=True)
		selected = set()
		maxs = [0] * n
		for i in range(n):
			(score, store, person) = person_store[i][0]
			maxs[person] = max(maxs[person], score)
			selected.add(store)
		if len(selected) <= n - 1:
			print(min(maxs))
			continue
		ans = 0
		for j in range(n):
			for k in range(j + 1, n):
				cur = float('inf')
				for i in range(n):
					if i == j or i == k:
						continue
					cur = min(cur, maxs[i])
				opt = 0
				for i in range(m):
					opt = max(opt, min(store_person[i][j], store_person[i][k]))
				cur = min(cur, opt)
				ans = max(ans, cur)
		print(ans)
	return

def main_whd():
	test = int(input())
	for _ in range(test):
		_ = input()
		(m, n) = map(int, input().split())
		shop_person = [[0] * n for _ in range(m)]
		for i in range(m):
			t = list(map(int, input().split()))
			for j in range(n):
				shop_person[i][j] = t[j]

		def check(x):
			cnt = [0] * m
			for i in range(n):
				t = 0
				for j in range(m):
					if shop_person[j][i] >= x:
						cnt[j] += 1
						t += 1
				if t == 0:
					return False
			if max(cnt) >= 2:
				return True
			return False
		(l, r) = (0, 10 ** 9)
		while l < r:
			mid = l + r + 1 >> 1
			if check(mid):
				l = mid
			else:
				r = mid - 1
		print(r)
	return
main_whd()


def check(r):
	flag = False
	cols = [False for i in range(n)]
	for i in range(m):
		kolvo = 0
		for j in range(n):
			if d[i][j] >= r:
				cols[j] = True
				kolvo += 1
		if kolvo >= 2:
			flag = True
	if flag and False not in cols:
		return True
	else:
		return False
t = int(input())
for i in range(t):
	input()
	(m, n) = map(int, input().split())
	d = []
	for j in range(m):
		d.append(list(map(int, input().split())))
	lev = 1
	prav = 10 ** 10
	u = (lev + prav) // 2
	while lev + 1 < prav:
		if check(u):
			lev = u
		else:
			prav = u
		u = (lev + prav) // 2
	print(lev)


def func():
	emp = input()
	(m, n) = map(int, input().split())
	inp = []
	for i in range(m):
		inp.append(list(map(int, input().split())))
	bdp = [-1 for i in range(n)]
	for i in range(m):
		for j in range(n):
			bdp[j] = max(bdp[j], inp[i][j])
	ans = min(bdp)
	if m < n:
		return ans
	req = -1
	for i in range(m):
		inp[i].sort(reverse=True)
		req = max(req, min(ans, inp[i][1]))
	return req
t = int(input())
for i in range(t):
	print(func())


for _ in range(int(input())):
	aaa = input()
	(m, n) = map(int, input().split())
	A = []
	for i in range(m):
		an = list(map(int, input().split()))
		A.append(an)
	l = 1
	ans = 1
	h = 10 ** 9
	last = -1
	while l <= h:
		mid = (l + h) // 2
		s = set()
		(can, can2) = (True, False)
		for j in range(n):
			can = False
			for i in range(m):
				if A[i][j] >= mid:
					can = True
					if i in s:
						can2 = True
					s.add(i)
			if not can:
				break
		if can and can2:
			l = mid + 1
			ans = mid
		else:
			h = mid - 1
	print(ans)


t = int(input())
for _ in range(t):
	_ = input()
	(m, n) = map(int, input().split())
	a = []
	for _ in range(m):
		a.append(list(map(int, input().split())))
	(mx, p) = ([0] * n, [0] * n)
	for i in range(m):
		for j in range(n):
			if a[i][j] > mx[j]:
				(mx[j], p[j]) = (a[i][j], i)
	ans = min(mx)
	if n <= m and len(set(p)) == n:
		ans = 0
		for i in range(n - 1):
			for j in range(i + 1, n):
				(t, t1, t2) = (0, mx[i], mx[j])
				for _ in range(m):
					t = max(t, min(a[_][i], a[_][j]))
				(mx[i], mx[j]) = (t, t)
				ans = max(ans, min(mx))
				(mx[i], mx[j]) = (t1, t2)
	print(ans)


for _ in range(int(input())):
	input()
	arr = [int(x) for x in input().split()]
	(m, n) = (arr[0], arr[1])
	arr = []
	for i in range(m):
		li = [int(x) for x in input().split()]
		arr.append(li)
	(high, low) = (10 ** 14, 0)
	ans = 0
	while low <= high:
		mid = (low + high) // 2
		s = set()
		can2 = False
		for j in range(n):
			can = False
			for i in range(m):
				if arr[i][j] >= mid:
					can = True
					if i in s:
						can2 = True
					else:
						s.add(i)
			if can == False:
				break
		if can and can2:
			ans = mid
			low = mid + 1
		else:
			high = mid - 1
	print(ans)


import sys, collections, math, bisect, heapq, random, functools, io, os, copy
input = sys.stdin.readline
out = sys.stdout.flush

def rep():
	a = list(map(int, input().split()))
	return a

def sep():
	a = list(input().split())
	return a

class UnionFind:

	def __init__(self, x) -> None:
		self.uf = [-1] * x

	def find(self, x):
		r = x
		while self.uf[x] >= 0:
			x = self.uf[x]
		while r != x:
			(self.uf[r], r) = (x, self.uf[r])
		return x

	def union(self, x, y):
		(ux, uy) = (self.find(x), self.find(y))
		if ux == uy:
			return
		if self.uf[ux] >= self.uf[uy]:
			self.uf[uy] += self.uf[ux]
			self.uf[ux] = uy
		else:
			self.uf[ux] += self.uf[uy]
			self.uf[uy] = ux
		return

	def __print__(self):
		return self.uf

def spfa(x, g, n):
	dis = [float('inf') for i in range(n)]
	dis[x] = 0
	state = [False for i in range(n)]
	state[x] = True
	queue = collections.deque()
	queue.append(x)
	while queue:
		cur = queue.popleft()
		state[cur] = False
		for next_ in g[cur]:
			if dis[next_] > dis[cur] + 1:
				dis[next_] = dis[cur] + 1
				if state[next_] == False:
					state[next_] = True
					queue.append(next_)
	return dis

def gcd(x, y):
	if y == 0:
		return x
	return gcd(y, x % y)

def valid(x, mat):
	(m, n) = (len(mat), len(mat[0]))
	cnt = [0 for i in range(m)]
	flag = [0 for i in range(n)]
	for i in range(m):
		for j in range(n):
			if mat[i][j] >= x:
				cnt[i] += 1
				flag[j] = 1
	return True if max(cnt) > 1 and sum(flag) == n else 0

def solve():
	t = input()
	(m, n) = map(int, input().split())
	matrix = [list(map(int, input().split())) for i in range(m)]
	(l, r) = (float('inf'), float('inf'))
	for j in range(n):
		temp = -float('inf')
		for i in range(m):
			temp = max(temp, matrix[i][j])
			l = min(l, matrix[i][j])
		r = min(r, temp)
	while l <= r:
		mid = l + (r - l) // 2
		if valid(mid, matrix):
			l = mid + 1
		else:
			r = mid - 1
	print(l - 1)
for i in range(int(input())):
	solve()


import sys
from sys import stdin, stdout
from math import ceil, floor, sqrt, log, log2, log10
from collections import Counter
int_max = float('inf')
int_min = -float('inf')
mod = 10 ** 9 + 7
ANS = []
input = stdin.readline

def solve():
	pass
t = int(input())
for i in range(t):
	x = input()
	(m, n) = map(int, input().split())
	grid = []
	maxx = [0] * n
	c = 0
	for i in range(m):
		a = list(map(int, input().split()))
		for j in range(n):
			maxx[j] = max(maxx[j], a[j])
		a.sort()
		c = max(c, a[n - 2])
	print(min(c, min(maxx)))


def solve():
	input()
	(m, n) = list(map(int, input().split()))
	p = []
	for _ in range(m):
		p.append(list(map(int, input().split())))

	def ops(num):
		flag = True
		temp = [0 for _ in range(m)]
		for j in range(n):
			tmp = 0
			for i in range(m):
				if p[i][j] >= num:
					temp[i] += 1
					tmp = 1
			if tmp == 0:
				flag = False
		return True if flag and max(temp) >= 2 else False
	(l, r) = (0, 10 ** 9 + 1)
	while r - l > 1:
		mid = l + r >> 1
		if ops(mid):
			l = mid
		else:
			r = mid
	print(l)
for _ in range(int(input())):
	solve()


def OK(x):
	a = [0 for i in range(n)]
	max_c = 0
	for i in range(m):
		c = 0
		for j in range(n):
			if s[i][j] >= x:
				a[j] = 1
				c += 1
		max_c = max(c, max_c)
	return all(a) and max_c > 1
for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	s = [list(map(int, input().split())) for i in range(m)]
	L = 1
	R = 10 ** 9 + 1
	while R - L > 1:
		M = (R + L) // 2
		if OK(M):
			L = M
		else:
			R = M
	print(L)


import sys
input = lambda : sys.stdin.readline().rstrip()
INF = 10 ** 19

def solve():
	(m, n) = map(int, input().split())
	p = [list(map(int, input().split())) for _ in range(m)]

	def check(x):
		canbuy = [[False for _ in range(n)] for _ in range(m)]
		buy = [set() for _ in range(m)]
		for i in range(m):
			for j in range(n):
				if p[i][j] >= x:
					canbuy[i][j] = True
		s = set()
		cann = set()
		for i in range(m):
			for j in range(n):
				if canbuy[i][j]:
					if i not in s:
						cann.add(j)
						s.add((i, j))
		if len(cann) != n:
			return False
		for (i, me) in s:
			for j in range(n):
				if canbuy[i][j] and j != me:
					return True
	ok = 0
	ng = 10 ** 18
	while abs(ok - ng) > 1:
		mid = (ok + ng) // 2
		if check(mid):
			ok = mid
		else:
			ng = mid
	print(ok)
t = int(input())
for _ in range(t):
	input()
	solve()


Z = input
Y = lambda : map(int, Z().split())
for _ in range(int(Z())):
	Z()
	(n, m) = Y()
	a = [[*Y()] for i in range(n)]
	print(min(min((max((a[j][i] for j in range(n))) for i in range(m))), max((sorted(a[i])[-2] for i in range(n)))))


from sys import stdin
import math
from collections import deque
from heapq import heapify, heappop, heappush
from bisect import bisect_left, bisect_right
input = stdin.readline

def log(n, m):
	(res, val) = (0, 1)
	while True:
		if n == val:
			return res
		elif n > val:
			return res - 1
		res += 1
		val *= m

def ceil(m, n):
	val = m // n
	if m % n != 0:
		return val + 1
	return val

def square(a, p, low, high):
	while low < high:
		mid = (low + high) // 2
		val = mid ** p
		if a > val:
			low = mid + 1
		elif a == val:
			return mid
		else:
			high = mid
	if low ** p > a:
		return low - 1
	else:
		return low
for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	(arr, seconds, fvals) = ([], 0, [0] * n)
	for _ in range(m):
		row = list(map(int, input().split()))
		for i in range(n):
			fvals[i] = max(row[i], fvals[i])
		row.sort()
		seconds = max(seconds, row[-2])
	print(min(seconds, min(fvals)))


from __future__ import division, print_function
import math
import sys
import os
from io import BytesIO, IOBase
from collections import deque, Counter, OrderedDict, defaultdict
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def inp():
	return int(input())

def inps():
	return input().strip()

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

def insr():
	s = input().strip()
	return list(s[:len(s)])

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

def check(k):
	val = [0 for i in range(m)]
	cnt = [0 for i in range(n)]
	for i in range(n):
		for j in range(m):
			if l[i][j] >= k:
				cnt[i] += 1
				val[j] = 1
	if max(cnt) > 1 and sum(val) == m:
		return 1
	return 0
for _ in range(inp()):
	inlt()
	(n, m) = invr()
	l = []
	for i in range(n):
		l.append(inlt())
	(lf, rt) = (1, 10 ** 9 + 5)
	while lf < rt - 1:
		mid = (lf + rt) // 2
		if check(mid):
			lf = mid
		else:
			rt = mid
	if check(rt):
		print(rt)
	else:
		print(lf)


import heapq
import sys
input = sys.stdin.readline
t = int(input())
ans = []
for _ in range(t):
	input()
	(m, n) = map(int, input().split())
	p = [list(map(int, input().split())) for _ in range(m)]
	if m <= n - 1:
		x = [0] * n
		for pi in p:
			for j in range(n):
				x[j] = max(x[j], pi[j])
		ans0 = min(x)
	else:
		h = []
		for i in range(m):
			pi = p[i]
			for j in range(n):
				heapq.heappush(h, (-pi[j], i, j))
		x = [0] * n
		y = [0] * m
		c = 0
		f1 = 0
		f2 = 0
		while h:
			(p0, i, j) = heapq.heappop(h)
			if not x[j]:
				x[j] = 1
				c += 1
			if y[i]:
				f1 = 1
			y[i] = 1
			if c == n:
				f2 = 1
			if f1 and f2:
				ans0 = -p0
				break
	ans.append(str(ans0))
sys.stdout.write('\n'.join(ans))


from collections import *
import sys
import io, os
import math
from heapq import *
gcd = math.gcd
sqrt = math.sqrt

def ceil(a, b):
	a = -a
	k = a // b
	k = -k
	return k
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def strinp(testcases):
	k = 5
	if testcases == -1 or testcases == 1:
		k = 1
	f = str(input())
	f = f[2:len(f) - k]
	return f

def main():
	t = int(input())
	for _ in range(t):
		input()
		arr = list(map(int, input().split()))
		m = arr[0]
		n = arr[1]
		p = [0] * m
		for i in range(m):
			p[i] = list(map(int, input().split()))
		f = []
		for i in range(n):
			l = []
			for j in range(m):
				l.append((p[j][i], j))
			l.sort(reverse=True)
			f.append(l)
		perm = [0] * (m + 1)
		mi = 10 ** 12
		for i in range(n):
			perm[f[i][0][1]] = 1
			mi = min(f[i][0][0], mi)
		if sum(perm) != n:
			print(mi)
			continue
		for i in range(m):
			for j in range(n):
				p[i][j] = (p[i][j], j)
			p[i].sort(reverse=True)
		ma = 0
		for i in range(m):
			a = p[i][0][1]
			b = p[i][1][1]
			ans = min(p[i][0][0], p[i][1][0])
			for j in range(n):
				if j == a or j == b:
					continue
				ans = min(ans, f[j][0][0])
			ma = max(ma, ans)
		print(ma)
main()


from collections import defaultdict, deque, Counter
from heapq import heapify, heappop, heappush
import math
from copy import deepcopy
from itertools import combinations, permutations, product, combinations_with_replacement
from bisect import bisect_left, bisect_right
import sys

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

def getN():
	return int(input())

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

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

def getListGraph():
	return list(map(lambda x: int(x) - 1, input().split()))

def getArray(intn):
	return [int(input()) for i in range(intn)]
mod = 10 ** 9 + 7
MOD = 998244353
inf = float('inf')
eps = 10 ** (-15)
dy = [0, 1, 0, -1]
dx = [1, 0, -1, 0]
T = getN()
for _ in range(T):
	q = input()
	(M, N) = getNM()
	A = [getList() for i in range(M)]

	def f(x):
		C = [0] * N
		ma = 0
		for i in range(M):
			ma_opt = 0
			for j in range(N):
				if A[i][j] >= x:
					C[j] += 1
					ma_opt += 1
			ma = max(ma, ma_opt)
		if all([c >= 1 for c in C]) and ma >= 2:
			return True
		else:
			return False
	(ok, ng) = (0, 10 ** 18)
	while abs(ng - ok) > 1:
		mid = (ok + ng) // 2
		if f(mid):
			ok = mid
		else:
			ng = mid
	print(ok)


from sys import stdin
input = stdin.readline
rn = lambda : int(input())
rns = lambda : map(int, input().split())
rl = lambda : list(map(int, input().split()))
rs = lambda : input().strip()
YN = lambda x: print('YES') if x else print('NO')
ceil_div = lambda a, b: -(-a // b)
mod = 10 ** 9 + 7
for _ in range(rn()):
	rs()
	(m, n) = rns()
	grid = [rl() for i in range(m)]
	lo = 1
	hi = 10 ** 9
	ans = 1
	while lo <= hi:
		mid = (lo + hi) // 2
		s = set()
		need = 0
		br = False
		for i in range(n):
			good = [j for j in range(m) if grid[j][i] >= mid]
			if len(good) == 0:
				br = True
				break
			f = False
			for num in good:
				if num in s:
					f = True
					break
				s.add(num)
			if not f:
				need += 1
		if need < n and (not br):
			ans = max(ans, mid)
			lo = mid + 1
		else:
			hi = mid - 1
	print(ans)


def main():

	def segfunc(x, y):
		return min(x, y)
	INF = 10 ** 10
	ide_ele = INF

	class SegTree:

		def __init__(self, init_val, segfunc, ide_ele):
			n = len(init_val)
			self.segfunc = segfunc
			self.ide_ele = ide_ele
			self.num = 1 << (n - 1).bit_length()
			self.tree = [ide_ele] * 2 * self.num
			for i in range(n):
				self.tree[self.num + i] = init_val[i]
			for i in range(self.num - 1, 0, -1):
				self.tree[i] = segfunc(self.tree[2 * i], self.tree[2 * i + 1])

		def update(self, k, x):
			k += self.num
			self.tree[k] = x
			while k > 1:
				self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
				k >>= 1

		def query(self, l, r):
			res = self.ide_ele
			l += self.num
			r += self.num
			while l < r:
				if l & 1:
					res = self.segfunc(res, self.tree[l])
					l += 1
				if r & 1:
					res = self.segfunc(res, self.tree[r - 1])
				l >>= 1
				r >>= 1
			return res

	def answer():
		(m, n) = map(int, input().split())
		p = [list(map(int, input().split())) for _ in range(m)]
		p = list(zip(*p))
		M = [max(p[i]) for i in range(n)]
		T = SegTree(M, segfunc, ide_ele)
		if n > m:
			print(min(M))
			return
		ans = -1
		for i in range(n - 1):
			tm = T.query(0, i)
			if tm == -1:
				tm = INF
			pi = p[i]
			for j in range(i + 1, n):
				pj = p[j]
				tmp = -1
				for k in range(m):
					tmp = max(tmp, min(pi[k], pj[k]))
				tij = T.query(i + 1, j)
				if tij == -1:
					tij = INF
				tj = T.query(j + 1, n)
				if tj == -1:
					tj = INF
				t_ans = min(tmp, tm, tij, tj)
				ans = max(ans, t_ans)
		print(ans)
	for _ in range(int(input())):
		x = input()
		answer()
main()


t = int(input())
for _ in range(t):
	input()
	(m, n) = [int(x) for x in input().split()]
	max_joy = [0] * n
	alfa = 0
	for i in range(m):
		shop = [int(joy) for joy in input().split()]
		for j in range(n):
			max_joy[j] = max(max_joy[j], shop[j])
		shop.sort()
		alfa = max(alfa, shop[n - 2])
	alfa = min(alfa, min(max_joy))
	print(alfa)


import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def main(t):
	s = input()
	(m, n) = map(int, input().split())
	friends = [[] for _ in range(n)]
	for i in range(m):
		temp = list(map(int, input().split()))
		for j in range(n):
			friends[j].append(temp[j])
	maximum = max(friends[0])
	for j in range(1, n):
		maximum = min(maximum, max(friends[j]))

	def judge(target):
		dic = {}
		for j in range(n):
			for i in range(m):
				if friends[j][i] >= target:
					if i in dic:
						return True
					dic[i] = 1
		return False
	front = 0
	rear = maximum + 1
	while front < rear:
		mid = (front + rear) // 2
		flag = judge(mid)
		if flag:
			front = mid + 1
		else:
			rear = mid
	ans = front - 1
	print(ans)
T = int(input())
t = 1
while t <= T:
	main(t)
	t += 1


def search(x, m, n, arr):
	pair = False
	valid = [False for _ in range(n)]
	for store in range(m):
		c = 0
		for friend in range(n):
			if arr[store][friend] >= x:
				valid[friend] = True
				c += 1
		if c >= 2:
			pair = True
	if not pair and m > 1:
		return False
	ans = True
	for truth in valid:
		ans = ans and truth
	return ans

def solve(m, n, arr):
	l = 0
	r = 10000000000.0
	dup = 0
	while l < r:
		mid = (l + r) // 2
		if mid == dup:
			return -1
		if search(mid, m, n, arr):
			if not search(mid + 1, m, n, arr):
				return int(mid)
			else:
				l = mid
		else:
			r = mid
		dup = mid
	return -1
tests = int(input())
for _ in range(tests):
	_ = input()
	(m, n) = map(int, input().split())
	arr = []
	for _ in range(m):
		arr.append(list(map(int, input().split())))
	print(solve(m, n, arr))


def solve(mid, p, m, n):
	for i in range(n):
		flag = 1
		for j in range(m):
			if p[j][i] >= mid:
				flag = 0
				break
		if flag == 1:
			return False
	for i in range(m):
		count = 0
		for j in range(n):
			if p[i][j] >= mid:
				count += 1
			if count >= 2:
				return True
	return False
t = int(input())
for _ in range(t):
	input()
	(m, n) = map(int, input().split())
	p = []
	mini = 10 ** 8
	maxi = 0
	mid = (mini + maxi) // 2
	for i in range(m):
		arr = list(map(int, input().split()))
		mini = min(mini, min(arr))
		maxi = max(maxi, max(arr))
		p.append(arr)
	ans = 0
	while mini <= maxi:
		mid = (mini + maxi) // 2
		if solve(mid, p, m, n):
			mini = mid + 1
			ans = max(ans, mid)
		else:
			maxi = mid - 1
	print(ans)


import sys

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

def get_max_2_value(arr):
	max_0 = -1
	max_1 = -1
	for i in range(len(arr)):
		if max_0 == -1 or arr[i] >= arr[max_0]:
			max_1 = max_0
			max_0 = i
		elif max_1 == -1 or arr[i] >= arr[max_1]:
			max_1 = i
	return arr[max_1]
t = int(read_line())
for _ in range(t):
	read_line()
	nm = read_line().split()
	m = int(nm[0])
	n = int(nm[1])
	p = [list(map(lambda x: int(x), read_line().split())) for _ in range(m)]
	max_possible = [max([p[i][x] for i in range(m)]) for x in range(n)]
	best_result = min(max_possible)
	if m < n:
		print(best_result)
	else:
		best_reduction = max([get_max_2_value(p[i]) for i in range(m)])
		print(min([best_reduction, best_result]))


q = int(input())
for qwerty in range(q):
	kpz70 = input()
	(x, y) = map(int, input().split())
	a = [0 for i in range(y)]
	b = 0
	for i in range(x):
		z = list(map(int, input().split()))
		for j in range(y):
			if z[j] > a[j]:
				a[j] = z[j]
		if x > y - 1:
			z.sort()
			if z[y - 2] > b:
				b = z[y - 2]
	if b > 0:
		a.append(b)
	print(min(a))


import sys
I = lambda : [*map(int, sys.stdin.readline().split())]
(t,) = I()
for _ in range(t):
	I()
	(m, n) = I()
	p = [I() for i in range(m)]
	q = [[p[i][j] for i in range(m)] for j in range(n)]
	big = [max(q[i]) for i in range(n)]
	if m < n:
		print(min(big))
		continue
	inds = [set(range(m)) for i in range(n)]
	ones = 0
	order = []
	for i in range(m):
		for j in range(n):
			order.append((p[i][j], i, j))
	order.sort()
	uses = [n] * m
	ind = 0
	done = False
	for i in range(m * n):
		(val, store, person) = order[i]
		inds[person].remove(store)
		uses[store] -= 1
		while ind < m and uses[ind] <= 1:
			ind += 1
		if ind == m:
			print(val)
			done = True
			break
		if len(inds[person]) == 0:
			print(val)
			done = True
			break
	if not done:
		print(min(big))


from sys import setrecursionlimit
from bisect import bisect_left, bisect_right
from collections import deque
from functools import lru_cache, reduce
from heapq import heappush, heappop
from math import sqrt, ceil, floor, log2
T = int(input())

def rl(t=int):
	return list(map(t, input().split()))
for t in range(1, T + 1):
	rl()
	(m, n) = rl()
	grid = []
	for _ in range(m):
		grid.append(rl())
	seconds = []
	bests = [set() for _ in range(m)]
	ideal = float('inf')
	for i in range(n):
		b1 = b2 = 0
		i1 = i2 = -1
		for j in range(m):
			this = grid[j][i]
			if this > b1:
				(b1, b2) = (this, b1)
				(i1, i2) = (j, i1)
			elif this > b2:
				b2 = this
				i2 = j
			else:
				pass
		ideal = min(ideal, b1)
		bests[i1].add(i)
		seconds.append(i2)
	if any((len(b) > 1 for b in bests)):
		print(ideal)
	else:
		ret = 0
		for cj in range(m):
			b1 = b2 = 0
			for el in grid[cj]:
				if el > b1:
					(b1, b2) = (el, b1)
				elif el > b2:
					b2 = el
				else:
					pass
			ret = max(ret, min([ideal, b1, b2]))
		print(ret)


import sys
import heapq
input = sys.stdin.readline
for _ in range(int(input())):
	input()
	(stores, people) = map(int, input().split())
	happines = []
	for __ in range(stores):
		happines.append(tuple(map(int, input().split())))
	maxx = [0] * people
	for i in range(people):
		for j in range(stores):
			maxx[i] = max(maxx[i], happines[j][i])
	bestTwo = [[-1, -1], [-1, -1]]
	for i in range(stores):
		x = heapq.nlargest(2, happines[i])
		if x[1] > bestTwo[1][0]:
			bestTwo = [[x[0], happines[i].index(x[0])], [x[1], happines[i].index(x[1])]]
	maxx[bestTwo[0][1]] = bestTwo[0][0]
	maxx[bestTwo[1][1]] = bestTwo[1][0]
	print(min(maxx))


from collections import defaultdict

def get_sol(d_fr, shops):
	for key in d_fr:
		d_fr[key].sort(reverse=True)
	shops_ideal = []
	min_ideal = float('inf')
	for key in d_fr:
		shops_ideal.append(d_fr[key][0][1])
		min_ideal = min(min_ideal, d_fr[key][0][0])
	shop_d = {i: True for i in shops_ideal}
	if len(shop_d) <= len(d_fr.keys()) - 1:
		return min_ideal
	else:
		val = 0
		for s_i in range(len(shops)):
			shops[s_i].sort(reverse=True)
			if s_i in shop_d:
				temp = min(min_ideal, shops[s_i][1])
				val = max(val, temp)
			else:
				temp = min(min_ideal, min(shops[s_i][:2]))
				val = max(val, temp)
		return val
for t in range(int(input())):
	blank = input()
	(m, n) = map(int, input().split())
	d_fr = defaultdict(lambda : [])
	shops = []
	for s_i in range(m):
		values = list(map(int, input().split()))
		shops.append(values)
		for f_i in range(len(values)):
			d_fr[f_i].append([values[f_i], s_i])
	print(get_sol(d_fr, shops))


def solve():

	def possible(k):
		a = [0 for i in range(n)]
		max_v = 0
		for i in range(m):
			c = 0
			for j in range(n):
				if arr[i][j] >= k:
					a[j] = 1
					c += 1
			max_v = max(max_v, c)
		return all(a) and max_v > 1
	input()
	(m, n) = map(int, input().split())
	arr = [list(map(int, input().split())) for _ in range(m)]
	(low, high) = (1, 10 ** 9 + 1)
	while low <= high:
		mid = low + high >> 1
		if possible(mid):
			ans = mid
			low = mid + 1
		else:
			high = mid - 1
	return ans
t = int(input())
while t:
	print(solve())
	t -= 1


import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
for _ in range(int(input())):
	input()
	(n, m) = [int(i) for i in input().split()]
	a = []
	ind = [0] * m
	for i in range(n):
		a.append([int(i) for i in input().split()])
		for j in range(m):
			if a[-1][j] > a[ind[j]][j]:
				ind[j] = i
	prev = [a[ind[i]][i] for i in range(m)]
	if len(set(ind)) != m:
		print(min(prev))
	else:
		l = 0
		r = 10 ** 9
		ans = 0
		while l <= r:
			mid = (l + r) // 2
			cnt = [0] * n
			flag = [0] * m
			for i in range(n):
				for j in range(m):
					if a[i][j] >= mid:
						flag[j] = 1
						cnt[i] += 1
			if max(cnt) > 1 and min(flag) == 1:
				ans = mid
				l = mid + 1
			else:
				r = mid - 1
		print(ans)


from sys import stdin, stdout, setrecursionlimit
from math import gcd, sqrt, factorial, pi, inf
from collections import deque, defaultdict
from bisect import bisect, bisect_left
from time import time
from itertools import permutations as per
from heapq import heapify, heappush, heappop, heappushpop
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\r\n')
L = lambda : list(R())
P = lambda x: stdout.write(str(x) + '\n')
lcm = lambda x, y: x * y // gcd(x, y)
nCr = lambda x, y: f[x] * inv(f[y] * f[x - y] % N) % N
inv = lambda x: pow(x, N - 2, N)
sumx = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7
for _ in range(I()):
	S()
	(m, n) = R()
	a = [1] * n
	p = 1
	mn = inf
	for i in range(m):
		x = L()
		p = max(p, sorted(x)[-2])
		for (j, k) in enumerate(x):
			a[j] = max(a[j], k)
	ans = min(a)
	if n - 1 < m:
		ans = min(ans, p)
	print(ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def transpose(arr):
	(r, c) = (len(arr), len(arr[0]))
	ans = [[arr[i][j] for i in range(r)] for j in range(c)]
	return ans

class SegmentTree:

	def __init__(self, a, fx, val):
		self.n = len(a)
		self.val = val
		self.fx = fx
		self.tree = [val] * self.n * 2
		for i in range(self.n):
			self.tree[i + self.n] = a[i]
		for i in range(self.n - 1, 0, -1):
			self.tree[i] = fx(self.tree[i << 1], self.tree[i << 1 | 1])

	def modify(self, p, value):
		(p, self.tree[p]) = (self.n + p, value)
		while p > 1:
			self.tree[p >> 1] = self.fx(self.tree[p], self.tree[p ^ 1])
			p >>= 1

	def query(self, l, r):
		(l, r, ans) = (l + self.n, r + self.n, self.val)
		while l < r:
			if l & 1:
				(ans, l) = (self.fx(ans, self.tree[l]), l + 1)
			if r & 1:
				(ans, r) = (self.fx(ans, self.tree[r - 1]), r - 1)
			(l, r) = (l >> 1, r >> 1)
		return ans

	def get(self, p):
		return self.tree[p + n]

def solve(num_shops, num_friends, fsjoytable, sfjoytable):
	foptimal_shop_index = [max(enumerate(fsjoytable[idx_friend]), key=lambda x: x[1])[0] for idx_friend in range(num_friends)]
	if len(foptimal_shop_index) == len(set(foptimal_shop_index)):
		maxjoy = [sfjoytable[idx_shop][idx_friend] for (idx_friend, idx_shop) in enumerate(foptimal_shop_index)]
		st = SegmentTree(maxjoy, min, 10 ** 12)
		final_ans = []
		for (idx_shop, shop) in enumerate(sfjoytable):
			ishop = sorted(enumerate(shop), key=lambda x: x[1], reverse=True)
			(fid_1, fid_2) = (ishop[0][0], ishop[1][0])
			(qp1, qp2) = (min(fid_1, fid_2), max(fid_1, fid_2))
			val = min(st.query(0, qp1), st.query(qp1 + 1, qp2), st.query(qp2 + 1, num_friends))
			final_ans.append(min(val, ishop[0][1], ishop[1][1]))
		return max(final_ans)
	else:
		joys = [sfjoytable[foptimal_shop_index[idx_friend]][idx_friend] for idx_friend in range(num_friends)]
		return min(joys)
for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	joytable = [list(map(int, input().split())) for _ in range(m)]
	val = solve(m, n, transpose(joytable), joytable)
	print(val)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))
for _ in range(int(input()) if True else 1):
	blank = input()
	(n, m) = map(int, input().split())
	p = []
	values = []
	alpha = 1
	omega = 1
	for i in range(n):
		p += [list(map(int, input().split()))]
		omega = max(omega, max(p[-1]))
	while alpha < omega:
		mid = (alpha + omega + 1) // 2
		st = set()
		pos = True
		common = False
		for j in range(m):
			found = False
			for i in range(n):
				if p[i][j] >= mid:
					found = True
					if i not in st:
						st.add(i)
					else:
						common = True
			if not found:
				pos = False
				break
		if pos and common:
			alpha = mid
		else:
			omega = mid - 1
	print(alpha)


import sys

def find(x):
	two = False
	ans = [False for _ in range(m)]
	for i in range(n):
		k = 0
		for j in range(m):
			if joys[i][j] >= x:
				k += 1
				ans[j] = True
		if k >= 2:
			two = True
	if two and all(ans):
		return True
	else:
		return False
k = int(sys.stdin.readline())
for _ in range(k):
	sys.stdin.readline()
	(n, m) = map(int, sys.stdin.readline().split())
	joys = []
	max_joy = 0
	min_joy = 10 ** 6
	for _ in range(n):
		joy = list(map(int, sys.stdin.readline().split()))
		joys.append(joy)
		(ma, mi) = (max(joy), min(joy))
		if max_joy < ma:
			max_joy = ma
		if min_joy > mi:
			min_joy = mi
	mid = (min_joy + max_joy) // 2
	while mid >= min_joy:
		if find(mid):
			min_joy = mid + 1
		else:
			max_joy = mid - 1
		mid = (min_joy + max_joy) // 2
	print(mid)


for _ in range(int(input())):
	input()
	(m, n) = list(map(int, input().split()))
	l = []
	maxx = 0
	for i in range(m):
		l.append(list(map(int, input().split())))
		maxx = max(maxx, max(l[-1]))
	(lft, rig) = (1, maxx + 1)
	l.sort(reverse=True)
	while lft < rig:
		(pos, ct, mid, vis) = (0, 0, (lft + rig + 1) // 2, [0] * n)
		for i in range(m):
			ct = 0
			for j in range(n):
				if l[i][j] >= mid:
					vis[j] = 1
					ct += 1
			if ct > 1:
				pos = 1
		pos = sum(vis) == n and pos
		if pos:
			lft = mid
		else:
			rig = mid - 1
	print(lft)


tests = int(input())
for _ in range(tests):
	input()
	(m, n) = [int(x) for x in input().split()]
	list = []
	for i in range(m):
		x = [int(x) for x in input().split()]
		list.append(x)
	temp = []
	res = 0
	for i in range(m):
		res = max(res, sorted(list[i])[-2])
	result = float('inf')
	for i in range(n):
		x = 0
		for j in range(m):
			x = max(list[j][i], x)
		result = min(result, x)
	print(min(result, res))


import os, sys
from io import BytesIO, IOBase
from types import GeneratorType
from bisect import *
from collections import defaultdict, deque, Counter
import math, string
from heapq import *
from operator import add
from itertools import accumulate
BUFSIZE = 8192
sys.setrecursionlimit(10 ** 5)

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
inf = float('inf')
en = lambda x: list(enumerate(x))
ceil_ = lambda a, b: (a + b - 1) // b
ii = lambda : int(input())
r = lambda : map(int, input().split())
rr = lambda : list(r())

def solve():
	(m, n) = r()
	arr = [rr() for _ in ' ' * m]
	ans = 0
	for i in arr:
		ans = max(ans, sorted(i)[-2])
	for j in range(n):
		x = 0
		for i in range(m):
			x = max(x, arr[i][j])
		ans = min(ans, x)
	print(ans)
for _ in ' ' * ii():
	input()
	solve()


from collections import deque
import heapq
import sys

def srch(arr, val, idx):
	for (id, i) in enumerate(arr):
		if id == idx:
			continue
		if i >= val:
			return True
	return False

def secondmax(arr):
	mx = max(arr[0], arr[1])
	id_mx = max(range(2), key=arr.__getitem__)
	smx = min(arr[0], arr[1])
	id_smx = min(range(2), key=arr.__getitem__)
	for i in range(2, len(arr)):
		if arr[i] >= mx:
			smx = mx
			id_smx = id_mx
			mx = arr[i]
			id_mx = i
		elif arr[i] >= smx:
			smx = arr[i]
			id_smx = i
	return (smx, id_smx, mx, id_mx)

def solve1(m, n, arr):
	mx_vals = []
	for i in range(m):
		mx_vals.append(secondmax(arr[i]))
	(smx, id_smx, mx, id_mx) = max(mx_vals)
	vals = [smx, mx]
	carr = list(zip(*arr))
	for i in range(n):
		if i == id_smx or i == id_mx:
			continue
		val = max(carr[i])
		vals.append(val)
	return min(vals)

def solve(m, n, arr):
	rnos = set()
	a = sys.maxsize
	cols = list(zip(*arr))
	mat = []
	cmat = []
	best = -1
	for i in range(n):
		rno = max(range(m), key=cols[i].__getitem__)
		rnos.add(rno)
		if cols[i][rno] < a:
			best = i
			a = cols[i][rno]
		mat.append(arr[rno])
	if len(rnos) < n:
		return a
	cmat = list(zip(*mat))
	flag = False
	for i in range(n):
		if i == best:
			continue
		tmp_arr = cmat[i]
		if srch(tmp_arr, a, i):
			return a
	smxs = [secondmax(cmat[i]) for i in range(n)]
	a = max(smxs)
	return a
t = int(input())
for i in range(t):
	_ = input()
	(m, n) = tuple(map(int, input().rstrip().split()))
	arr = []
	for _ in range(m):
		arr.append(list(map(int, input().rstrip().split())))
	ans = solve1(m, n, arr)
	print(ans)


import sys
from bisect import bisect_left as lb
from bisect import bisect_right as rb
from collections import deque
from queue import PriorityQueue as pq
from math import gcd
input_ = lambda : sys.stdin.readline().strip('\r\n')
ii = lambda : int(input_())
il = lambda : list(map(int, input_().split()))
ilf = lambda : list(map(float, input_().split()))
lii = lambda : list(map(int, list(ip())))
ip = lambda : input_()
fi = lambda : float(input_())
ap = lambda ab, bc, cd: ab[bc].append(cd)
li = lambda : list(input_())
pr = lambda x: print(x)
prinT = lambda x: print(x)
f = lambda : sys.stdout.flush()
inv = lambda x: pow(x, mod - 2, mod)
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
mod = 10 ** 9 + 7
mod1 = 998244353
for _ in range(ii()):
	ip()
	(m, n) = il()
	a = []
	for i in range(m):
		a.append(il())
	mn = float('inf')
	for i in range(n):
		x = 0
		for j in range(m):
			x = max(x, a[j][i])
		mn = min(x, mn)
	ans = 0
	l = 0
	h = 10 ** 9 + 2
	while l <= h:
		mid = (l + h) // 2
		f = 0
		for i in range(m):
			t = 0
			for j in range(n):
				if a[i][j] >= mid:
					t += 1
			if t > 1:
				f = 1
				break
		if f:
			l = mid + 1
			ans = mid
		else:
			h = mid - 1
	print(min(ans, mn))


def czy_sie_da(x, sklepy, iloS, iloO):
	osoTmp = [False] * iloO
	for i in range(iloO):
		for j in range(iloS):
			if sklepy[j][i] >= x:
				osoTmp[i] = True
	if False in osoTmp:
		return False
	for i in range(iloS):
		tmp = 0
		for j in range(iloO):
			if sklepy[i][j] >= x:
				tmp += 1
				if tmp == 2:
					return True
	return False

def main():
	iloP = int(input())
	for i in range(iloP):
		input()
		(iloS, iloO) = list(map(int, input().split()))
		sklepy = [0] * iloS
		for j in range(iloS):
			sklepy[j] = list(map(int, input().split()))
		pocz = 0
		kon = 10 ** 9
		wyn = 0
		while pocz < kon:
			mid = (pocz + kon + 1) // 2
			if czy_sie_da(mid, sklepy, iloS, iloO):
				pocz = mid
				wyn = max(mid, wyn)
			else:
				kon = mid - 1
		print(wyn)
main()


t = int(input())
p = []
(m, n) = (0, 0)

def check(mid):
	flag = False
	person = [False] * n
	for i in range(m):
		c = 0
		for j in range(n):
			if p[i][j] >= mid:
				person[j] = True
				c = c + 1
		if c > 1:
			flag = True
	if not flag and n > 1:
		return False
	ans = True
	for i in range(n):
		ans = ans & person[i]
	return ans
for _ in range(t):
	input()
	p = []
	(m, n) = map(int, input().split(' '))
	for _ in range(m):
		p.append(list(map(int, input().split(' '))))
	(l, r) = (0, 10 ** 9)
	while l < r:
		mid = (l + r + 1) // 2
		if check(mid):
			l = mid
		else:
			r = mid - 1
	print(l)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
import math
import collections
from itertools import permutations
from itertools import combinations

def prob():
	input()
	(m, n) = [int(x) for x in input().split()]
	ans = 0
	grid = []
	for i in range(m):
		l = [int(x) for x in input().split()]
		grid.append(l)
		p = sorted(l)
		ans = max(ans, p[-2])
	for i in range(n):
		c = 0
		for j in range(m):
			c = max(c, grid[j][i])
		ans = min(ans, c)
	print(ans)
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = 1
t = int(input())
for _ in range(0, t):
	prob()


def happywith(x):
	happy = [False] * friends
	possible = False
	for shop in range(shops):
		count = 0
		for friend in range(friends):
			if mat[shop][friend] >= x:
				happy[friend] = True
				count += 1
		if count > 1:
			possible = True
	return possible and all(happy)
for _ in range(int(input())):
	_ = input()
	(shops, friends) = map(int, input().strip().split())
	mat = (*((*map(int, input().split()),) for i in range(shops)),)
	if shops < friends:
		print(min((max((mat[shop][friend] for shop in range(shops))) for friend in range(friends))))
	else:
		right = 1
		while happywith(right):
			right *= 2
		left = right // 2
		while left < right - 1:
			mid = (left + right) // 2
			if happywith(mid):
				left = mid
			else:
				right = mid
		print(left)


t = int(input())
for t in range(t):
	input()
	(m, n) = list(map(int, input().split()))
	a = [[0] * n for i in range(m)]
	for i in range(m):
		a[i] = list(map(int, input().split()))

	def chk(x):
		ok = 1
		c = [0] * m
		for j in range(n):
			tmp = 0
			for i in range(m):
				if a[i][j] >= x:
					c[i] += 1
					tmp = 1
			if tmp == 0:
				ok = 0
		if ok and max(c) >= 2:
			return 1
		return 0
	l = 0
	r = 1000000000 + 1
	while r - l > 1:
		mid = l + r >> 1
		if chk(mid):
			l = mid
		else:
			r = mid
	print(l)


def check(b, c, m, n, k):
	if m <= n - 1:
		return min(*b) >= k
	return min(*b) >= k and max(*c) >= k

def solve():
	input()
	a = list(map(int, input().split(' ')))
	m = a[0]
	n = a[1]
	a = [list(map(int, input().split(' '))) for i in range(m)]
	b = [0 for i in range(n)]
	c = [0 for i in range(m)]
	r = 0
	for i in range(m):
		for j in range(n):
			r = max(r, a[i][j])
			b[j] = max(b[j], a[i][j])
		a[i].sort()
		c[i] = a[i][n - 2]
	l = 1
	ans = r
	while l <= r:
		mid = l + r >> 1
		if check(b, c, m, n, mid):
			ans = mid
			l = mid + 1
		else:
			r = mid - 1
	print(ans)
for t in range(int(input())):
	solve()


import sys

def new_years_problem(m, n, joy_by_shop):
	best_present_by_friend = [0] * n
	for i in range(m):
		for j in range(n):
			best_present_by_friend[j] = max(best_present_by_friend[j], joy_by_shop[i][j])
	best_present_with_min_joy = min(best_present_by_friend)
	optimal_joy = 0
	if n > m:
		return best_present_with_min_joy
	for i in range(m):
		joys = sorted(zip(joy_by_shop[i], range(n)), key=lambda x: -x[0])
		optimal_joy = max(optimal_joy, min(best_present_with_min_joy, joys[1][0]))
	return optimal_joy
for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	joy_by_shop = [None] * m
	for i in range(m):
		joy_by_shop[i] = list(map(int, input().split()))
	sys.stdout.write(f'{new_years_problem(m, n, joy_by_shop)}\n')


twoPowers = []
bb = 1
while bb < 1000000000.0:
	twoPowers.append(bb)
	bb *= 2
twoPowers.reverse()

def main():

	def check(alpha):
		hasLarger = [False] * n
		for i in range(m):
			for j in range(n):
				if p[i][j] >= alpha:
					hasLarger[j] = True
		if False in hasLarger:
			return False
		for i in range(m):
			cnts = 0
			for j in range(n):
				if p[i][j] >= alpha:
					cnts += 1
			if cnts >= 2:
				return True
		return False
	t = int(input())
	allans = []
	for _ in range(t):
		input()
		(m, n) = readIntArr()
		p = []
		for __ in range(m):
			p.append(readIntArr())
		ans = 0
		for bb in twoPowers:
			if check(ans + bb):
				ans += bb
		allans.append(ans)
	multiLineArrayPrint(allans)
	return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(a, b, c):
	print('? {} {} {}'.format(a, b, c))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ansArr):
	print('! {}'.format(' '.join([str(x) for x in ansArr])))
	sys.stdout.flush()
inf = float('inf')
from math import gcd, floor, ceil
import math
for _abc in range(1):
	main()


import sys
t = int(input())
for _ in range(t):
	sys.stdin.readline()
	(m, n) = map(int, input().split())
	lst = []
	res = 0
	for i in range(m):
		ll = list(map(int, input().split()))
		lst.append(ll)
		res = max(res, sorted(lst[-1])[-2])
	for i in range(n):
		aa = 0
		for j in range(m):
			aa = max(aa, lst[j][i])
		res = min(res, aa)
	print(res)


from bisect import *
import sys
input = sys.stdin.readline

def inp():
	return int(input())

def st():
	return input().rstrip('\n')

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

def ma():
	return map(int, input().split())
t = inp()
while t:
	t -= 1
	x = st()
	(m, n) = ma()
	maxx = [[] for i in range(n)]
	r = []
	for i in range(m):
		a = lis()
		r.append(a)
		for j in range(n):
			maxx[j].append([a[j], i])
	for i in range(n):
		maxx[i].sort()
	z = set()
	z1 = float('inf')
	for i in range(n):
		z.add(maxx[i][-1][1])
	if len(z) != n:
		for i in range(n):
			z1 = min(z1, maxx[i][-1][0])
		print(z1)
	else:
		z1 = 0
		for i in range(n):
			for j in range(i + 1, n):
				z2 = float('inf')
				for k in range(n):
					if k != i and k != j:
						z2 = min(z2, maxx[k][-1][0])
				for k in range(m):
					z3 = min(z2, r[k][i], r[k][j])
					z1 = max(z1, z3)
		print(z1)


for _ in range(int(input())):
	input()
	(n, m) = map(int, input().split())
	rd = []
	for i in range(m):
		rd.append(0)
	top2 = []
	for i in range(n):
		fr = list(map(int, input().split()))
		tt = [0, 0]
		for f in range(m):
			if fr[f] > rd[f]:
				rd[f] = fr[f]
			if fr[f] > tt[1]:
				if fr[f] >= tt[0]:
					tt[1] = tt[0]
					tt[0] = fr[f]
				else:
					tt[1] = fr[f]
		top2.append(tt[1])
	a = min((rd[i] for i in range(m)))
	b = max(top2)
	print(min(a, b))


import collections

def max_two(array):
	(i, j) = (0, 1)
	if array[0] < array[1]:
		(i, j) = (1, 0)
	for k in range(2, len(array)):
		if array[k] >= array[i]:
			(i, j) = (k, i)
		elif array[k] >= array[j]:
			(i, j) = (i, k)
	return (i, j)

def solve():
	input()
	(m, n) = list(map(int, input().split()))
	p = []
	for _ in range(m):
		p += [list(map(int, input().split()))]
	max_joy = collections.defaultdict(int)
	for shop in range(m):
		for friend in range(n):
			max_joy[friend] = max(max_joy[friend], p[shop][friend])
	ans = 0
	for shop in range(m):
		(i, j) = max_two(p[shop])
		min_joy = p[shop][j]
		for friend in range(n):
			if friend == i or friend == j:
				continue
			min_joy = min(min_joy, max_joy[friend])
		ans = max(ans, min_joy)
	print(ans)
for _ in range(int(input())):
	solve()


import sys, array, bisect, collections, heapq, itertools, math, functools
sys.setrecursionlimit(100000)

def _r():
	return sys.stdin.buffer.readline()

def rs():
	return _r().decode('ascii').strip()

def rn():
	return int(_r())

def rnt():
	return tuple(map(int, _r().split()))

def rnl():
	return list(rnt())

def rna():
	return array.array('q', rnt())

def pnl(l):
	print(' '.join(map(str, l)))

def solve(m, n, p):
	(l, r) = (1, float('inf'))
	for i in range(n):
		r = min(r, max((store[i] for store in p)))
	if m <= n - 1:
		return r

	def _try(x):
		for store in p:
			if sum((fg >= x for fg in store)) > 1:
				return True
		return False
	sol = 0
	while l <= r:
		mid = l + (r - l) // 2
		if _try(mid):
			sol = mid
			l = mid + 1
		else:
			r = mid - 1
	return sol
for _ in range(rn()):
	rs()
	(m, n) = rnt()
	p = []
	for _ in range(m):
		p.append(rnl())
	print(solve(m, n, p))


def solve(m, n, lst):
	temp = []
	res = 0
	for i in range(m):
		res = max(res, sorted(lst[i])[-2])
	result = 10 ** 9
	for i in range(n):
		x = 0
		for j in range(m):
			x = max(lst[j][i], x)
		result = min(result, x)
	print(min(result, res))
t = int(input())
for i in range(t):
	x = input()
	(m, n) = map(int, input().split())
	lst = []
	for i in range(m):
		temp = list(map(int, input().split()))
		lst.append(temp)
	solve(m, n, lst)


from sys import stdin
input = stdin.readline

def answer():
	ans = float('inf')
	for i in range(n):
		ans = min(ans, max(joy[i]))
	ansval = -float('inf')
	for i in range(m):
		ansval = max(ansval, min(ans, shop[i]))
	return ansval
for T in range(int(input())):
	input().strip()
	(m, n) = map(int, input().split())
	shop = [0 for i in range(m)]
	joy = [[] for i in range(n)]
	for i in range(m):
		x = list(map(int, input().split()))
		for j in range(n):
			joy[j].append(x[j])
		shop[i] = sorted(x)[-2]
	print(answer())


from sys import stdin
for _ in range(int(input())):
	x = input()
	(s, f) = map(int, stdin.readline().split())
	shops = [i for i in range(f)]
	d = set()
	mat = []
	for i in range(s):
		m = list(map(int, stdin.readline().split()))
		mat.append(m)
	l = []
	for j in range(f):
		M = 0
		ind = -1
		for i in range(s):
			if mat[i][j] >= M:
				M = mat[i][j]
				ind = i
		shops[j] = ind
		d.add(ind)
		l.append(M)
	ans = -1
	if len(d) < f:
		ans = min(l)
		print(ans)
	if ans == -1:
		M = 0
		for i in range(s):
			mat[i].sort(reverse=True)
			M = max(M, mat[i][1])
		print(min(min(l), M))


for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	p = []
	for i in range(m):
		a = list(map(int, input().split()))
		for j in range(n):
			p.append([a[j], i, j])
	p.sort()
	got = False
	sf = set()
	ss = set()
	for i in range(m * n - 1, -1, -1):
		sf.add(p[i][2])
		if p[i][1] in ss:
			got = True
		ss.add(p[i][1])
		if len(sf) == n and got:
			ans = p[i][0]
			break
	print(ans)


import sys
import math
import collections
import heapq
dy = [1, 0, -1, 0]
dx = [0, 1, 0, -1]
r = lambda : sys.stdin.readline().rstrip()
MIS = lambda : map(int, r().split())
for _ in range(int(r())):
	r()
	(M, N) = MIS()
	if N <= M:
		ML = [[] for _ in range(N)]
		MM = [0] * N
		L = []
		for j in range(M):
			a = list(MIS())
			for i in range(N):
				if MM[i] < a[i]:
					MM[i] = a[i]
					ML[i] = [j]
				elif MM[i] == a[i]:
					ML[i].append(j)
			L.append(a)
		s = set()
		flag = 0
		for i in range(N):
			for j in ML[i]:
				if j in s:
					flag = 1
				else:
					s.add(j)
		ans = MM[0]
		for i in range(1, N):
			if ans > MM[i]:
				ans = MM[i]
		if flag:
			print(ans)
		else:
			aa = ans + 0
			ans = 0
			for i in range(M):
				temp = 0
				tempp = 0
				t = aa + 0
				for j in range(N):
					if temp < L[i][j]:
						tempp = temp
						temp = L[i][j]
					elif tempp < L[i][j]:
						tempp = L[i][j]
				ans = max(ans, min(aa, tempp))
			print(ans)
	else:
		L = []
		for _ in range(M):
			L.append(list(MIS()))
		ans = 9543595435495345
		for j in range(N):
			temp = 0
			for i in range(M):
				if temp < L[i][j]:
					temp = L[i][j]
			if temp < ans:
				ans = temp
		print(ans)


from collections import Counter, defaultdict, deque
import bisect
from sys import stdin, stdout
from itertools import repeat
import math

def inp(force_list=False):
	re = list(map(int, input().split()))
	if len(re) == 1 and (not force_list):
		return re[0]
	return re

def inst():
	return input().strip()

def gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x
MOD = 998244353

def query(a, b, c):
	print('! %d %d %d' % (a + 1, b + 1, c + 1))
	stdout.flush()
	return inp()

def solve():
	(n, k) = map(int, input().split())
	a = list(map(int, input().split()))
	a = sorted(a)
	cost = sum(a[0:n - 2 * k]) + sum(map(lambda x: a[x + n - 2 * k] // a[x + n - k], range(0, k)))
	print(cost)

def my_main():
	kase = inp()
	pans = []
	for _ in range(kase):
		inp()
		(m, n) = inp()
		da = []
		for i in range(m):
			da.append(inp(True))
		if m <= n - 1:
			ans = int(1000000000.0 + 7)
			for j in range(n):
				tans = 0
				for i in range(m):
					tans = max(tans, da[i][j])
				ans = min(ans, tans)
			pans.append(str(ans))
		else:
			(l, r) = (1, int(1000000000.0 + 1))
			while l < r - 1:
				mid = (l + r) // 2
				ck = []
				lonley = 0
				ok = 1
				for j in range(n):
					sm = 0
					for i in range(m):
						if da[i][j] >= mid:
							sm += 1
					if sm == 0:
						ok = 0
				if ok:
					ok = 0
					for i in range(m):
						if sum((j >= mid for j in da[i])) > 1:
							ok = 1
				if ok:
					l = mid
				else:
					r = mid
			pans.append(str(l))
	print('\n'.join(pans))
my_main()


import sys
import io, os
input = sys.stdin.buffer.readline
from collections import Counter, defaultdict
t = int(input())
for _ in range(t):
	blank = input()
	(m, n) = map(int, input().split())
	P = [list(map(int, input().split())) for i in range(m)]

	def is_ok(x):
		C = Counter()
		D = defaultdict(lambda : [])
		for i in range(n):
			for j in range(m):
				if P[j][i] >= x:
					C[j] += 1
					D[i].append(j)
			if not D[i]:
				return False
		for i in range(n):
			for j in D[i]:
				if C[j] >= 2:
					return True
		return False
	ok = 0
	ng = 10 ** 9 + 50
	while ok + 1 < ng:
		c = (ng + ok) // 2
		if is_ok(c):
			ok = c
		else:
			ng = c
	print(ok)


t = int(input())
for i in range(t):
	input()
	(x, y) = ([], [])
	(n, m) = map(int, input().split())
	for j in range(n):
		x.append(list(map(int, input().split())))
	for j in range(n):
		for g in range(m):
			y.append([x[j][g], j, g])
	y.sort()
	y.reverse()
	found = [0 for i in range(m)]
	deg = [0 for j in range(n)]
	deg2 = False
	rem = m
	for [v, i, j] in y:
		deg[i] += 1
		if deg[i] >= 2:
			deg2 = True
		if found[j] == 0:
			rem -= 1
			found[j] = 1
		if deg2 and rem == 0:
			print(v)
			break


def main():
	test = int(input())
	for idt in range(test):
		_ = input()
		(m, n) = map(int, input().split())
		store_person = [[0] * n for _ in range(m)]
		for i in range(m):
			a = list(map(int, input().split()))
			for j in range(n):
				store_person[i][j] = a[j]
		person_store = [[] for _ in range(n)]
		for i in range(n):
			for j in range(m):
				person_store[i].append([store_person[j][i], j, i])
			person_store[i].sort(reverse=True)
		selected = set()
		maxs = [0] * n
		for i in range(n):
			(score, store, person) = person_store[i][0]
			maxs[person] = max(maxs[person], score)
			selected.add(store)
		if len(selected) <= n - 1:
			print(min(maxs))
			continue
		ans = 0
		for j in range(n):
			for k in range(j + 1, n):
				cur = float('inf')
				for i in range(n):
					if i == j or i == k:
						continue
					cur = min(cur, maxs[i])
				opt = 0
				for i in range(m):
					opt = max(opt, min(store_person[i][j], store_person[i][k]))
				cur = min(cur, opt)
				ans = max(ans, cur)
		print(ans)
	return
main()


import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
	input()
	(m, n) = map(int, input().split())
	s = []
	for i in range(m):
		s.append(list(map(int, input().split())))
	g = []
	for i in range(n):
		x = []
		for j in range(m):
			x.append(s[j][i])
		g.append(x)
	ans = 10 ** 9
	vis = [0] * m
	for i in range(n):
		M = max(g[i])
		ans = min(M, ans)
		for j in range(m):
			if g[i][j] == M:
				vis[j] += 1
	f = 0
	for i in range(m):
		if vis[i] > 1:
			f = 1
			break
	if f:
		print(ans)
	else:
		x = 0
		for j in range(m):
			s[j].sort()
			x = max(x, s[j][n - 2])
		ans = min(ans, x)
		print(ans)


for _ in range(int(input())):
	input()
	(m, n) = map(int, input().split())
	happiness = [[int(x) for x in input().split()] for _ in range(m)]
	max_happiness_by_friend = [max((hap[i] for hap in happiness)) for i in range(n)]
	max_happiness_by_shop = [0] * m
	for (i, hap) in enumerate(happiness):
		hap.sort()
		max_happiness_by_shop[i] = hap[-2]
	mmhbs = max(max_happiness_by_shop)
	mmhbf = min(max_happiness_by_friend)
	print(min(mmhbs, mmhbf))


def find(arr, m, n):
	maxArr = [0] * n
	for j in range(n):
		for i in range(m):
			if arr[i][j] > maxArr[j]:
				maxArr[j] = arr[i][j]
	r = min(maxArr)
	l = 0
	ans = 0
	while r >= l:
		mid = (r + l) // 2
		for i in range(m):
			count = 0
			for j in range(n):
				if arr[i][j] >= mid:
					count += 1
			if count > 1:
				ans = mid
				l = mid + 1
				break
		if count < 2:
			r = mid - 1
	return ans
res = []
r = int(input())
for i in range(r):
	input()
	[m, n] = list(map(int, input().split()))
	arr = []
	for i in range(m):
		arr.append(list(map(int, input().split())))
	res.append(find(arr, m, n))
for i in res:
	print(i)


from __future__ import print_function
from math import *
from collections import deque
import os
import sys
from io import BytesIO, IOBase

def main():
	pass
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
mod = 10 ** 9 + 7

def inp():
	return int(input())

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

def insr():
	s = input()
	return list(s[:len(s)])

def invr():
	return map(int, input().split())
for _ in range(inp()):
	k = input()
	(m, n) = invr()
	l = []
	for i in range(m):
		l.append(inlt())
	x = []
	y = []
	yy = []
	for i in range(n):
		mi = -1
		ma = -1
		for j in range(m):
			if l[j][i] > ma:
				ma = l[j][i]
				mi = j
		x.append(mi)
		y.append(ma)
	if m < n:
		print(min(y))
		continue
	xx = x[:]
	x.sort()
	f = 0
	mi = min(y)
	for i in range(n - 1):
		if x[i] == x[i + 1]:
			f = 1
	if f:
		print(min(y))
		continue
	x = []
	for i in range(m):
		l[i].sort()
		if l[i][-2] < mi:
			x.append(l[i][-2])
		else:
			x.append(mi)
	print(max(x))


numeroTestes = int(input())
results = []
for a in range(numeroTestes):
	input()
	(lojas, amigos) = [int(t) for t in input().split()]
	presentesPorLojas = []
	for i in range(lojas):
		pesentes = [int(x) for x in input().split()]
		presentesPorLojas.append(pesentes)
	res = 0
	for i in range(lojas):
		res = max(res, sorted(presentesPorLojas[i])[-2])
	result = float('inf')
	for i in range(amigos):
		maioDiversao = 0
		for j in range(lojas):
			maioDiversao = max(presentesPorLojas[j][i], maioDiversao)
		result = min(result, maioDiversao)
	results.append(min(res, result))
for r in results:
	print(r)