#include <stdio.h>
#include <vector>
#include <algorithm>
#define MMAX 30100
#define NMAX 15100
using namespace std;
struct muchie
{
int x, y, cost;
} edge[MMAX];
struct par
{
int son, cost;
};
vector <par> A[NMAX];
int n, T[NMAX], R[NMAX], Lev[2 * NMAX], First[NMAX], E[2 * NMAX], RM[15][2 * NMAX], Lg[2 * NMAX], LevNode[NMAX];
int x[15][NMAX], best[15][NMAX];
bool used[NMAX];
inline int max2 (int X, int Y)
{
if (X > Y)
return X;
return Y;
}
inline par makePar (int X, int Y)
{
par aux;
aux.son = X;
aux.cost = Y;
return aux;
}
inline bool comp (muchie A, muchie B)
{
return A.cost < B.cost;
}
int getFather (int x)
{
int root = x, aux;
while (root != T[root])
root = T[root];
while (x != root)
{
aux = T[x];
T[x] = root;
x = aux;
}
return root;
}
void unite (int x, int y)
{
if (R[x] <= R[y])
{
T[x] = y;
if (R[x] == R[y])
R[y] ++;
}
else
T[y] = x;
}
void getAPM (int N, int M)
{
int i, x, y;
sort (edge + 1, edge + M + 1, comp);
for (i = 1; i <= N; i ++)
T[i] = i, R[i] = 1;
for (i = 1; i <= M; i ++)
{
x = getFather (edge[i].x);
y = getFather (edge[i].y);
if (x == y)
continue;
A[edge[i].x].push_back (makePar (edge[i].y, edge[i].cost));
A[edge[i].y].push_back (makePar (edge[i].x, edge[i].cost));
unite (x, y);
}
}
void DF (int X, int L)
{
vector <par> :: iterator it;
par now;
used[X] = 1;
E[++ n] = X;
Lev[n] = L;
LevNode[X] = L;
First[X] = n;
for (it = A[X].begin (); it != A[X].end (); it ++)
{
now = *it;
if (used[now.son])
continue;
DF (now.son, L + 1);
E[++ n] = X;
Lev[n] = L;
x[0][now.son] = X;
best[0][now.son] = now.cost;
}
}
void PreprocessLogs (int N)
{
int i;
Lg[1] = 0;
for (i = 2; i <= N; i ++)
Lg[i] = Lg[i >> 1] + 1;
}
void getLCA (int N)
{
int i, j, step;
DF (1, 1);
//RMQ
for (i = 1; i <= n; i ++)
RM[0][i] = i;
for (i = 1; (1 << i) <= n; i ++)
{
step = 1 << i;
for (j = 1; j <= n; j ++)
{
if (j + step - 1 > n)
break;
if (Lev[RM[i - 1][j]] < Lev[RM[i - 1][j + (1 << (i - 1))]])
RM[i][j] = RM[i - 1][j];
else
RM[i][j] = RM[i - 1][j + (1 << (i - 1))];
}
}
PreprocessLogs (n);
}
int LCA (int X, int Y)
{
X = First[X]; Y = First[Y];
if (X > Y)
{
int aux = X;
X = Y;
Y = aux;
}
int le = Lg[Y - X + 1];
if (Lev[RM[le][X]] < Lev[RM[le][Y - (1 << le) + 1]])
return E[RM[le][X]];
else
return E[RM[le][Y - (1 << le) + 1]];
}
void Dinamica (int N) //bag ideea de la prob stramosi
{
int i, j, lastNode;
for (i = 1; (1 << i) <= N; i ++)
for (j = 1; j <= N; j ++)
{
lastNode = x[i - 1][j];
x[i][j] = x[i - 1][lastNode];
best[i][j] = max2 (best[i - 1][j], best[i - 1][lastNode]);
}
}
int Solve (int X, int Y)
{
int step = LevNode[X] - LevNode[Y], sol = 0, i;
for (i = 0; (1 << i) <= step; i ++)
if (step & (1 << i))
{
sol = max2 (sol, best[i][X]);
X = x[i][X];
}
return sol;
}
int main ()
{
int i, N, M, Q, X, Y, lc;
freopen ("radiatie.in", "r", stdin);
freopen ("radiatie.out", "w", stdout);
scanf ("%d%d%d", &N, &M, &Q);
for (i = 1; i <= M; i ++)
scanf ("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].cost);
getAPM (N, M);
getLCA (N);
Dinamica (N);
while (Q --)
{
scanf ("%d%d", &X, &Y);
lc = LCA (X, Y);
printf ("%d\n", max2 (Solve (X, lc), Solve (Y, lc)));
}
return 0;
}