#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define sz(x) (int)(x.size())
const int N = 15005, len = 17, Q = 1005, mod = 1e9 + 7;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int n, m, k, parent[N], sz[N], up[N][len + 1], rmq[N][len + 1];
int out[N], in[N], timer;
vector<pair<int, pair<int, int>>> edges;
vector<pair<int, int>> g[N];
int find_root(int x) {
if (parent[x] == x)
return x;
return parent[x] = find_root(parent[x]);
}
void unite(int x, int y) {
int a = find_root(x);
int b = find_root(y);
if (a != b) {
if (sz[a] < sz[b]) {
sz[b] += sz[a];
parent[a] = b;
} else {
sz[a] += sz[b];
parent[b] = a;
}
}
}
void compute(int u, int p = 0, int prev_weight = 0) {
in[u] = ++timer;
up[u][0] = p;
rmq[u][0] = prev_weight;
for (int i = 1; i <= len; i++) {
up[u][i] = up[up[u][i - 1]][i - 1];
rmq[u][i] = max(rmq[u][i - 1], rmq[up[u][i - 1]][i - 1]);
}
for (auto e: g[u]) {
if (e.first != p) {
compute(e.first, u, e.second);
}
}
out[u] = ++timer;
}
inline bool is_ancestor(int u, int v) {
return in[u] <= in[v] && out[u] >= out[v];
}
int query(int u, int v) {
int max_weight = 0;
if (is_ancestor(u, v))
return 0;
for (int i = len; i >= 0; i--) {
if (!is_ancestor(up[u][i], v)) {
max_weight = max(max_weight, rmq[u][i]);
u = up[u][i];
}
}
max_weight = max(max_weight, rmq[u][0]);
return max_weight;
}
int main() {
freopen("radiatie.in", "r", stdin);
freopen("radiatie.out", "w", stdout);
int t = 1;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
parent[i] = i, sz[i] = 1;
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
edges.pb({c, {a, b}});
}
sort(edges.begin(), edges.end());
for (int i = 0; i < m; i++) {
int A = find_root(edges[i].second.first);
int B = find_root(edges[i].second.second);
if (A != B) {
g[edges[i].second.first].pb({edges[i].second.second, edges[i].first});
g[edges[i].second.second].pb({edges[i].second.first, edges[i].first});
unite(A, B);
}
}
compute(1);
while (k--) {
int x, y;
cin >> x >> y;
cout << max(query(x, y), query(y, x)) << '\n';
}
}