#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define FIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define vi vector<ll>
#define pb push_back
#define F first
#define S second
#define all(v) (v).begin(),(v).end()
#define pii pair<ll,ll>
#define vii vector<pii>
#define MOD 1000000007LL
#define calc_fact(n) tgamma(n+1)

//disjoint set Union

ll find_set(ll x,vi& parent)
{
    if(parent[x]==-1)return x;
    
    return find_set(parent[x],parent);
}

void union_set(ll x,ll y,vi& parent)
{
    ll xroot=find_set(x,parent),yroot=find_set(y,parent);
    if(xroot!=yroot)
    parent[yroot]=xroot;
}

signed main()
{
    FIO;
    ll t;
    cin>>t;
    while(t--){
    ll n,m,ans=LONG_LONG_MAX;
    cin>>n>>m;
    vector<pii> adj[n];
    vi parent(n,-1);
    vector<pair<ll,pii>> edge;
    
    // Kruskal Algorithmn for maximum Spanning Tree
    
    for(ll i=0;i<m;i++)
    {
        ll a,b,c;
        cin>>a>>b>>c;a--;b--;
        edge.pb({c,{a,b}});
    }
    //sorting edge weight in decreasing order
    
    sort(edge.rbegin(),edge.rend());
    for(ll i=0;i<m;i++)
    {
        ll x=find_set(edge[i].S.F,parent),y=find_set(edge[i].S.S,parent);
        if(x!=y)
        {
            union_set(x,y,parent);
            adj[edge[i].S.F].pb({edge[i].S.S,edge[i].F});
            adj[edge[i].S.S].pb({edge[i].S.F,edge[i].F});
        }
    }
    vector<bool> visited(n,false);
    
    //BFS
    
    queue<ll> q;
    q.push(0);
    while(!q.empty())
    {
        ll v=q.front();
        q.pop();
        for(ll u=0;u<adj[v].size();u++)
        {
            if(!visited[adj[v][u].F])
            {
                visited[adj[v][u].F]=true;
                q.push(adj[v][u].F);
                ans=min(ans,adj[v][u].S);
            }
        }
    }
    
    // if not reachable or graph is disconnected
    
    if(!visited[n-1])
    ans=-1;
    cout<<ans<<"\n";
    }
}