// source code of submission 542687, Zhongshan University Online Judge System
//经典的最小生成树算法(基于并查集)首先,要对所有边按权从小到大排序,
//其次,要淘汰一些边,即使它们的权很小,但在生成树中它们是多余的(即构成环),
//这里我们可以用并查集来解决。每选取一条边,我们就把这条边的两个顶点放进同一个连通分量
//通过一个能够寻找连通分量根结点的函数find(v)来判断。如果find(v1)==find(v2),那么v1和v2
//已经属于同一连通分量,那么v1与v2间的边就不能再添加到生成树中。第三,什么时候结束算法呢?
//可以设置一个计数器,当已经添加了n-1条边时,生成树就构造好了。
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
struct Node{
int beg,end,dis;
bool operator < (const Node &y) const{
return dis<y.dis;
}
};
int N,d,index,m,ans;
Node edge[500*499/2];
int par[501];
int find(int x){
if (x == par[x])
return x;
else{
par[x] = find(par[x]);
return par[x];
}
}
int main(){
int T;
scanf("%d",&T);
while (T--){
index = 0;
scanf("%d",&N);
for (int i=0;i<N;i++){
for (int j=0;j<N;++j){
scanf("%d",&d);
if (j>i){
edge[index].beg = i;
edge[index].end = j;
edge[index].dis = d;
index ++;
}
}
}
sort(edge,edge+index);
m = 0;
ans = 0;
for (int i=0;i<N;i++) par[i] = i;
for (int i=0;i<index;++i){
if ( find(edge[i].beg) != find(edge[i].end)){
m++;
ans = edge[i].dis;
par[find(edge[i].beg)] = par[find(edge[i].end)];
if (m == N-1) break;
}
}
printf("%d\n",ans);
if (T!=0) printf("\n");
}
return 0;
}