#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <utility>
using namespace std;
const int MAX_N = 15100;
const int LG = 16;
struct edge{
int a, b, cost;
};
bool comp(const edge &a, const edge &b){
return a.cost < b.cost;
}
edge E[MAX_N * 2];
vector< pair<int ,int> > G[MAX_N];
char buff[32677];
int n,m,k;
int TT[MAX_N];
int under[MAX_N];
inline int father(const int node){
if(TT[node] == 0)
return node;
const int up = father(TT[node]);
TT[node] = up;
return up;
}
bool unite(const int a, const int b){
const int a_up = father(a),
b_up = father(b);
if(a_up == b_up)
return false;
if(under[a_up] >= under[b_up]){
under[a_up] += under[b_up] + 1;
TT[b_up] = a_up;
} else {
under[b_up] += under[a_up] + 1;
TT[a_up] = b_up;
}
return true;
}
int up[LG][MAX_N];
int cost[LG][MAX_N];
void ancestor(){
for(int i = 1 ; i < LG ; ++i){
for(int j = 1 ; j <= n ; ++ j){
up[i][j] = up[i-1][up[i-1][j]];
cost[i][j] = cost[i-1][j];
const int upper = cost[i-1][up[i-1][j]];
if(upper > cost[i][j])
cost[i][j] = upper;
}
}
}
int line[MAX_N * 2];
int fst[MAX_N];
int lvl[MAX_N];
int CR;
bool viz[MAX_N];
void DFS(const int node){
++CR;
fst[node] = CR;
viz[node] = 1;
line[CR] = node;
for(unsigned int i = 0 ; i < G[node].size() ; ++i){
const int son = G[node][i].first,
price = G[node][i].second;
if(viz[son])
continue;
up[0][son] = node;
cost[0][son] = price;
lvl[son] = lvl[node] + 1;
DFS(son);
++CR;
line[CR] = node;
}
}
int RMQ[MAX_N * 2][LG];
int lg[MAX_N * 2];
void build_RMQ(){
for(int i = 2 ; i <= CR ; ++i)
lg[i] = lg[i/2] + 1;
for(int i = 1 ; i <= CR ; ++i)
RMQ[i][0] = lvl[line[i]];
for(int j = 1 ; j < LG ; ++j){
for(int i = 1 ; i + (1 << j) - 1 <= CR ; ++i){
const int one = RMQ[i][j-1],
other = RMQ[i + (1 << j-1)][j-1];
RMQ[i][j] = one;
if(other < RMQ[i][j])
RMQ[i][j] = other;
}
}
}
int RMQuery(const int lo, const int hi){
const int delta = (hi - lo);
const int p2 = lg[delta];
const int one = RMQ[lo][p2],
other = RMQ[hi + 1 - (1 << p2)][p2];
return min(one, other);
}
int LCA(const int a, const int b){
const int one = fst[a], two = fst[b];
if(one <= two)
return RMQuery(one, two);
else return RMQuery(two, one);
}
int go_up(const int origin, const int levels){
int now = origin,
left = levels,
ret = 0;
for(int i = LG - 1 ; i >= 0 && levels ; --i){
while((1 << i) <= left){
left -= 1 << i;
const int path = cost[i][now];
if(path > ret)
ret = path;
now = up[i][now];
}
}
return ret;
}
void queries(){
while(k--){
int a,b;
scanf("%d%d", &a, &b);
const int root = LCA(a, b);
const int one = go_up(a, lvl[a] - root),
other = go_up(b, lvl[b] - root);
printf("%d\n", max(one, other));
}
}
int main(){
freopen("radiatie.in", "r", stdin);
freopen("radiatie.out", "w", stdout);
setvbuf(stdin, buff, _IOFBF, sizeof(buff));
scanf("%d%d%d", &n, &m, &k);
for(int i = 0 ; i < m ; ++i)
scanf("%d%d%d", &E[i].a, &E[i].b, &E[i].cost);
sort(E, E + m, comp);
for(int i = 0 ; i < m ; ++i){
if(unite(E[i].a, E[i].b)){
G[E[i].a].push_back(make_pair(E[i].b, E[i].cost));
G[E[i].b].push_back(make_pair(E[i].a, E[i].cost));
}
}
DFS(1);
build_RMQ();
ancestor();
queries();
}