#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
const string txt = "rediatie";
const long long nmax = 1e5;
ifstream f(txt + ".in");
ofstream g(txt + ".out");
struct ceva {
long long vec, c;
};
struct kr {
long long x, y, c;
};
struct aint {
long long n, val[4 * nmax];
void upd(long long poz, long long x) { update(1, 1, n, poz, x); }
long long maxi(long long x, long long y) { return query(1, 1, n, x, y); }
void update(long long nod, long long l, long long r, long long poz, long long x)
{
if (l == r) { val[nod] = x; return; }
long long mid = (l + r) / 2;
if (poz <= mid) update(2 * nod, l, mid, poz, x);
else update(2 * nod + 1, mid + 1, r, poz, x);
val[nod] = max(val[2 * nod], val[2 * nod + 1]);
}
long long query(long long nod, long long l, long long r, long long x, long long y)
{
if (x <= l && r <= y) return val[nod];
long long mid = (l + r) / 2;
long long ans = 0;
if (x <= mid) ans = max(ans, query(2 * nod, l, mid, x, y));
if (y > mid) ans = max(ans, query(2 * nod + 1, mid + 1, r, x, y));
return ans;
}
} a;
long long n, m, q, num[nmax], r[nmax], p[nmax], deep[nmax], cnt[nmax], cost[nmax], t[nmax], bi[nmax][25];
vector<long long> v[nmax];
vector<ceva> v2[nmax];
vector<kr> e;
static void dfs(long long nod, long long prev = 0)
{
p[nod] = prev; cnt[nod] = 1;
deep[nod] = deep[prev] + 1;
long long poz = 0;
for (long long i = 0; i < v[nod].size(); i++)
{
long long x = v[nod][i];
if (x == prev) continue;
dfs(x, nod);
cnt[nod] += cnt[x];
if (cnt[x] > cnt[v[nod][poz]]) poz = i;
}
if (poz) swap(v[nod][0], v[nod][poz]);
}
long long ind = 1;
static void hld(long long nod, long long prev = 0)
{
num[nod] = ind++;
for (long long i = 0; i < v[nod].size(); i++)
{
long long x = v[nod][i];
if (x == prev) continue;
r[x] = (i == 0 ? r[nod] : x);
hld(x, nod);
}
}
static long long answ(long long x, long long y)
{
long long ans = 0;
for (; r[x] != r[y]; x = p[r[x]])
{
if (deep[r[x]] < deep[r[y]]) swap(x, y);
ans = max(ans, a.maxi(num[r[x]], num[x]));
}
if (deep[x] < deep[y]) swap(x, y);
for (auto z : v[y]) if (z != p[y] && r[z] == r[x]) { y = z; break; }
ans = max(ans, a.maxi(num[y], num[x]));
return ans;
}
static long long root(long long x)
{
if (t[x] < 0) return x;
long long aux = root(t[x]);
t[x] = aux;
return t[x];
}
static void join(long long x, long long y)
{
long long rx = root(x), ry = root(y);
if (t[rx] < t[ry]) {
t[rx] += t[ry];
t[ry] = rx;
}
else {
t[ry] += t[rx];
t[rx] = ry;
}
}
static bool cmp(kr x, kr y) {
return x.c < y.c;
}
static void Kruskal()
{
for (long long i = 1; i <= n; i++) t[i] = -1;
sort(e.begin(), e.end(), cmp);
for (auto b : e)
{
long long x = b.x, y = b.y, c = b.c;
if (root(x) != root(y)) {
join(x, y);
v2[x].push_back({ y, c });
v2[y].push_back({ x, c });
}
}
}
static void make_tree(long long nod, long long prev = 0)
{
bi[nod][0] = prev;
for (long long i = 1; i <= 20; i++)
bi[nod][i] = bi[bi[nod][i - 1]][i - 1];
for (auto x : v2[nod])
{
if (x.vec == prev) continue;
v[x.vec].push_back(nod);
v[nod].push_back(x.vec);
cost[x.vec] = x.c;
make_tree(x.vec, nod);
}
}
static long long lca(long long x, long long y)
{
if (deep[x] < deep[y]) swap(x, y);
if (deep[x] != deep[y]) {
long long dif = deep[x] - deep[y];
for (long long i = 0; i <= 20; i++)
if (dif & (1 << i)) x = bi[x][i];
}
for (long long i = 20; i >= 0; i--)
if (bi[x][i] != bi[y][i])
x = bi[x][i], y = bi[y][i];
return (x == y ? x : bi[x][0]);
}
int main()
{
f >> n >> m >> q;
for (long long i = 1; i <= m; i++) {
long long x, y, c;
f >> x >> y >> c;
e.push_back({ x, y, c });
}
Kruskal(); make_tree(1);
dfs(1); r[1] = 1; hld(1); a.n = n;
for (long long i = 1; i <= n; i++) a.upd(num[i], cost[i]);
for (long long i = 1; i <= q; i++)
{
long long x, y; f >> x >> y;
long long l = lca(x, y);
g << max(answ(x, l), answ(y, l)) << '\n';
}
return 0;
}