#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
ifstream in ("radiatie.in") ;
ofstream out ("radiatie.out") ;
const int NR = 15005 ;
vector < pair < int , int > > v [ NR ] ;
int n , m , q , TT [ NR ] , GR [ NR ] , cnt , euler [ 2 * NR ] , rmq [ 20 ][ 2 * NR ] , lg [ 2 * NR ] , lvl [ NR ] , firstap [ NR ] ;
int rmq_edge [ 20 ][ 2 * NR ] , rmq_father [ 20 ][ 2 * NR ] ;
struct muchie
{
int x,y, cost ;
}e [ NR * 2 ];
bool cmp ( const muchie &i , const muchie &j )
{
return i.cost < j.cost ;
}
int find_root ( int x )
{
int root , y ;
for ( root = x ; root != TT [ root ] ; root = TT [ root ] ) ;
for ( ; x != TT [ x ] ; )
{
y = TT [ x ] ;
TT [ x ] = root ;
x = y ;
}
return root ;
}
void unite ( const int i , const int j )
{
if ( GR [ i ] < GR [ j ] ) TT [ i ] = j ;
else TT [ j ] = i ;
if ( GR [ i ] == GR [ j ] ) GR [ i ] ++ ;
}
void dfs ( const int nod , const int father )
{
euler[ ++ cnt ] = nod ;
firstap [ nod ] = cnt ;
for ( vector < pair < int , int > > :: iterator it = v [ nod ].begin() ; it != v [ nod ].end() ; ++ it )
{
if ( (*it).first == father ) continue ;
rmq_edge [ 0 ][ (*it).first ] = (*it).second ;
rmq_father [ 0 ][ (*it).first ] = nod ;
lvl [ (*it).first ] = lvl [ nod ] + 1 ;
dfs ( (*it).first , nod ) ;
euler [ ++ cnt ] = nod ;
}
}
void range()
{
int i , j ;
for ( i = 2 ; i <= cnt ; ++ i ) lg [ i ] = lg [ i >> 1 ] + 1 ;
for ( i = 1 ; i <= cnt ; ++ i ) rmq [ 0 ][ i ] = euler [ i ] ;
for ( i = 1 ; ( 1 << i ) <= cnt ; ++ i )
for ( j = 1 ; j + ( 1 << i ) <= cnt + 1 ; ++ j )
{
rmq [ i ][ j ] = rmq [ i - 1 ][ j ] ;
if ( lvl [ rmq [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ] < lvl [ rmq [ i ] [ j ] ] )
rmq [ i ][ j ] = rmq [ i - 1 ][ j + ( 1 << ( i - 1 ) ) ] ;
}
for ( i = 1 ; ( 1 << i ) <= n ; ++ i )
for ( j = 1 ; j <= n ; j ++ )
rmq_father [ i ][ j ] = rmq_father [ i - 1 ][ rmq_father [ i - 1 ][ j ] ] ;
for ( i = 1 ; ( 1 << i ) <= n ; ++ i )
for ( j = 1 ; j <= n ; j ++ )
rmq_edge [ i ][ j ] = max ( rmq_edge [ i - 1 ][ rmq_father [ i - 1 ][ j ] ] , rmq_edge [ i - 1 ][ j ] ) ;
}
int lca ( int i , int j )
{
int logg , sol ;
i = firstap [ i ] ;
j = firstap [ j ] ;
if ( i > j ) swap ( i , j ) ;
logg = lg [ j - i + 1 ] ;
sol = rmq [ logg ][ i ] ;
if ( lvl [ rmq [ logg ][ j - ( 1 << logg ) + 1 ] ] < lvl [ sol ] )
sol = rmq [ logg ][ j - ( 1 << logg ) + 1 ] ;
return sol ;
}
int maxedge ( int nod , int lc )
{
if ( lc == nod ) return 0 ;
int logg , dist , sol , k ;
logg = lg [ lvl [ nod ] - lvl [ lc ] ] ;
dist = lvl [ nod ] - lvl [ lc ] - ( 1 << logg ) ;
sol = rmq_edge [ logg ][ nod ] ;
k = lg [ n ] ;
while ( k -- )
if ( ( 1 << k ) & dist ) nod = rmq_father [ k ][ nod ] ;
return max ( sol , rmq_edge [ logg ][ nod ] ) ;
}
int main()
{
int i , x , y , cost , r1 , r2 , nre = 0 , lc ;
in >> n >> m >> q ;
for ( i = 1 ; i <= n ; ++ i ) TT [ i ] = i , GR [ i ] = 1 ;
for ( i = 1 ; i <= m ; ++ i )
{
in >> x >> y >> cost ;
e [ i ].x = x ;
e [ i ].y = y ;
e [ i ].cost = cost ;
}
sort ( e + 1 , e + m + 1 , cmp ) ;
for ( i = 1 ; i <= m && nre < n - 1 ; ++ i )
{
r1 = find_root ( e [ i ].x ) ;
r2 = find_root ( e [ i ].y ) ;
if ( r2 != r1 )
{
unite( r1 , r2 ) ;
v [ e [ i ].x ].pb ( mp ( e [ i ].y , e [ i ].cost ) ) ;
v [ e [ i ].y ].pb ( mp ( e [ i ].x , e [ i ].cost ) ) ;
}
}
dfs( 1 , 0 ) ;
range() ;
while ( q -- )
{
in >> x >> y ;
lc = lca ( x , y ) ;
out << max ( maxedge ( y , lc ) , maxedge ( x , lc ) ) << '\n' ;
}
}