#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
#define MAX_L 64010
#define inf (1 << 31) - 1
int fol[MAX_L], tata[MAX_L], nivel[MAX_L];
int n, m, i, j, k, val, p , q, nr, sol, X, Y;
int euler[2 * MAX_L], adanc[2 * MAX_L];
int ap[MAX_L][2];
int str[MAX_L][25], Max[MAX_L][25];
int rmq[2 * MAX_L][25];
int raw[MAX_L][3], vine[MAX_L], v[MAX_L];
vector <int> a[MAX_L], c[MAX_L];
inline int cmp(int x, int y) {
return raw[x][2] < raw[y][2];
}
int tata_comp(int nod) {
if (vine[nod] != nod) {
int v = tata_comp(vine[nod]);
vine[nod] = v;
return v;
}
else return nod;
}
void apm() {
for (i = 1; i <= n; i++)
vine[i] = i;
vine[n + 1] = n + 1;
sort(v + 1, v + m + 1, cmp);
//parcurg muchiile si construiesc apm - ul
for (i = 1; i <= m + n; i++) {
//vad daca nodurile fac parte din aceeasi componenta
if (tata_comp(raw[v[i]][0]) != tata_comp(raw[v[i]][1])) {
if (raw[v[i]][2] == inf) raw[v[i]][2] = 0;
a[raw[v[i]][0]].push_back(raw[v[i]][1]); c[raw[v[i]][0]].push_back(raw[v[i]][2]);
a[raw[v[i]][1]].push_back(raw[v[i]][0]); c[raw[v[i]][1]].push_back(raw[v[i]][2]);
//modific pozitia tatalui
vine[tata_comp(raw[v[i]][0])] = tata_comp(raw[v[i]][1]);
}
}
}
void cit() {
freopen("radiatie.in", "r", stdin);
freopen("radiatie.out", "w", stdout);
scanf("%d %d %d", &n, &m, &nr);
for (i = 1; i <= m; v[i] = i, i++)
scanf("%d %d %d", &raw[i][0], &raw[i][1], &raw[i][2]);
for (i = 1; i <= n; v[i + m] = i + m, i++) {
raw[m + i][0] = i;
raw[m + i][1] = n + 1;
raw[m + i][2] = inf;
}
apm();
}
void dfs(int w, int depth) {
euler[++k] = w; adanc[k] = depth;
nivel[w] = depth;
int l = a[w].size();
for (int i = 0; i < l; i++)
if (fol[a[w][i]] == 0) {
Max[a[w][i]][0] = c[w][i];
fol[a[w][i]] = 1; tata[a[w][i]] = w;
dfs(a[w][i], depth + 1);
fol[a[w][i]] = 0;
euler[++k] = w; adanc[k] = depth;
}
}
void solve() {
fol[n + 1] = 1; k = 0;
dfs(n + 1, 1);
for (i = 1; i <= k; i++) {
if (ap[euler[i]][0] == 0) ap[euler[i]][0] = i;
ap[euler[i]][1] = i;
rmq[i][0] = adanc[i];
}
for (j = 1; (1 << j) <= k; j++)
for (i = 1; i <= k; i++) {
rmq[i][j] = rmq[i][j - 1];
if (i + (1 << (j - 1)) <= k && rmq[i][j] > rmq[i + (1 << (j - 1))][j - 1])
rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];
}
//calculez al 1 << k - lea stramos al unui nod
for (i = 1; i <= n; i++) str[i][0] = tata[i];
for (j = 1; j <= 20; j++) {
for (i = 1; i <= n; i++)
str[i][j] = str[str[i][j - 1]][j - 1];
}
//calculez maximul pe intervalul i..i + 1<<k
for (j = 1; (1 << j) <= n; j++) {
for (i = 1; i <= n; i++) {
Max[i][j] = Max[i][j - 1];
if (nivel[i] - (1 << j) > 0)
Max[i][j] = max(Max[i][j - 1], Max[str[i][j - 1]][j - 1]);
}
}
}
int maxim(int nod, int niv) {
int p2 = 20, curent = 0;
int k = nivel[nod], x = nod;
while (k > niv && p2) {
while (k - (1 << p2) < niv && p2) p2--;
curent = max(curent, Max[x][p2]);
x = str[x][p2];
k = nivel[x];
}
return curent;
}
void write() {
for (i = 1; i <= nr; i++) {
scanf("%d %d", &X, &Y);
if (ap[X][0] < ap[Y][0]) p = ap[X][0];
else p = ap[Y][0];
if (ap[X][1] > ap[Y][1]) q = ap[X][1];
else q = ap[Y][1];
for (j = 0; j <= 20; j++)
if (p + (1 << j) > q) break;
j--;
if (rmq[p][j] <= rmq[q - (1 << j)][j]) val = rmq[p][j];
else val = rmq[q - (1 << j)][j];
//lca -ul intre nodurile X si Y se va afla la adancimea val
sol = max(maxim(X, val), maxim(Y, val));
printf("%d\n",sol);
}
}
int main() {
cit();
solve();
write();
return 0;
}