#include <bits/stdc++.h>
#define ll long long
#define pp pair< int, int >
#define tt tuple< int, int, int >
using namespace std;
const int mxn = 15 * 1000 + 10;
const int mxx = 2e9;
vector< pp > graf[ mxn ];
vector< int > partial[ mxn ];
ll dist[ mxn ];
int nivel[ 2 * mxn ];
int parcurgere[ mxn ];
int poz[ mxn ];
int p;
int arb[ 8 * mxn ], arb_daddy[ 8 * mxn ];
int n, m, k;
int a, b;
inline tt atribuire(pp muchie, int daddy){
return make_tuple(muchie.first, muchie.second, daddy);
}
void construire_partial(){
priority_queue< tt, vector< tt >, greater< tt > > q_min;
bitset< mxn > viz;
int ramas = n - 1;
for(auto it: graf[ 1 ])
q_min.push( atribuire( it, 1 ) );
viz[ 1 ] = 1;
int cost, nod, daddy;
while(!q_min.empty() && ramas > 0){
tie(cost, nod, daddy) = q_min.top();
q_min.pop();
if(viz[ nod ] == 0){
partial[ daddy ].push_back( nod );
ramas--;
viz[ nod ] = 1;
dist[ nod ] = cost;
for(auto it: graf[ nod ])
q_min.push( atribuire( it, nod ) );
}
}
}
void euler(int nod, int lvl){
nivel[ nod ] = lvl;
poz[ nod ] = p;
parcurgere[ p++ ] = nod;
for(auto it: partial[ nod ]){
euler( it, lvl + 1 );
parcurgere[ p++ ] = nod;
}
}
void construire_minim(int nod, int st, int sf){
if(st == sf){
arb[ nod ] = parcurgere[ st ];
}
else{
int mid = (st + sf) / 2;
int p1 = 2 * nod;
int p2 = 2 * nod + 1;
construire_minim(p1, st, mid);
construire_minim(p2, mid + 1, sf);
if(dist[ arb[ p1 ] ] >= dist[ arb[ p2 ] ])
arb[ nod ] = arb[ p1 ];
else
arb[ nod ] = arb[ p2 ];
}
}
void construire_daddy(int nod, int st, int sf){
if(st == sf){
arb_daddy[ nod ] = parcurgere[ st ];
}
else{
int mid = (st + sf) / 2;
int p1 = 2 * nod;
int p2 = 2 * nod + 1;
construire_daddy(p1, st, mid);
construire_daddy(p2, mid + 1, sf);
if(nivel[ arb[ p1 ] ] <= nivel[ arb[ p2 ] ])
arb_daddy[ nod ] = arb_daddy[ p1 ];
else
arb_daddy[ nod ] = arb_daddy[ p2 ];
}
//cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
}
int query(int nod, int st, int sf){
if(st >= a && sf <= b){
//cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
return arb_daddy[ nod ];
}
else{
if(!(st > b || sf < a)){
int mid = (st + sf) / 2;
int d1 = query(2 * nod, st, mid);
int d2 = query(2 * nod + 1, mid + 1, sf);
if(nivel[ d1 ] < nivel[ d2 ])
return d1;
else
return d2;
}
}
return 0;
}
int query_f(int nod, int st, int sf){
if(st >= a && sf <= b){
//cout<< st << ' ' << sf << ' ' << arb_daddy[ nod ] << '\n';
return arb[ nod ];
}
else{
if(!(st > b || sf < a)){
int mid = (st + sf) / 2;
int d1 = query_f(2 * nod, st, mid);
int d2 = query_f(2 * nod + 1, mid + 1, sf);
if(dist[ d1 ] >= dist[ d2 ])
return d1;
else
return d2;
}
}
return 0;
}
int main()
{
ifstream cin("radiatie.in");
ofstream cout("radiatie.out");
cin>> n >> m >> k;
for(int i = 1, x, y, z; i <= m; i++){
cin>> x >> y >> z;
graf[ x ].push_back(make_pair(z, y));
graf[ y ].push_back(make_pair(z, x));
}
construire_partial();
euler(1, 1);
construire_minim(1, 0, p - 1);
construire_daddy(1, 0, p - 1);
for(int i = 1, x, y; i <= k; i++){
cin>> x >> y;
a = poz[ x ];
b = poz[ y ];
if(b < a)
swap(a, b);
nivel[ 0 ] = mxx;
int daddy = query(1, 0, p - 1);
nivel[ 0 ] = 0;
a = poz[ daddy ] + 1;
b = poz[ x ];
int d1 = dist[ query_f(1, 0, p - 1) ];
b = poz[ y ];
int d2 = dist[ query_f(1, 0, p - 1) ];
cout<< max(d1, d2) << '\n';
}
return 0;
}