#include <queue>
#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
const int NMAX = 15000, LOGNMAX = 14;
struct edge
{
int v1, v2, w;
};
bool operator < (const edge& x, const edge& y)
{return x.w < y.w;}
struct dirEdge
{
int v, w;
};
int euler[2 * NMAX - 1], h[2 * NMAX - 1], wes[2 * NMAX - 2], log2[2 * NMAX + 1];
int spTblH[2 * NMAX - 1][LOGNMAX + 1], spTblW[2 * NMAX - 1][LOGNMAX + 1];
int ind;
bool vis[NMAX];
vector<dirEdge> lists[NMAX];
vector<dirEdge> apmEdges[NMAX];
vector<int> pos[NMAX];
priority_queue<edge> myHeap;
void initApm(int n);
void initLog2();
void buildEuler(int node, int currH);
void initSptbls(int n);
int queryHeight(int lo, int hi);
int queryWeight(int lo, int hi);
int getLCA(int v1, int v2);
int getMax(int v1, int v2);
int main()
{
int n, m, k, i, v1, v2;
edge e;
FILE *fin = fopen("radiatie.in", "r");
fscanf(fin, "%d%d%d", &n, &m, &k);
for (i = 0; i < m; i++)
{
fscanf(fin, "%d%d%d", &e.v1, &e.v2, &e.w);
lists[e.v1 - 1].push_back({e.v2 - 1, e.w});
lists[e.v2 - 1].push_back({e.v1 - 1, e.w});
}
initApm(n);
buildEuler(0, 0);
initLog2();
initSptbls(n * 2 - 1);
FILE *fout = fopen("radiatie.out", "w");
for (i = 0; i < k; i++)
{
fscanf(fin, "%d%d", &v1, &v2);
fprintf(fout, "%d\n", getMax(v1 - 1, v2 - 1));
}
fclose(fin);
fclose(fout);
return 0;
}
void initApm(int n)
{
int i, len, cpn;
edge e;
vis[0] = 1;
len = lists[0].size();
for (i = 0; i < len; i++)
myHeap.push({0, lists[0][i].v, lists[0][i].w});
cpn = n;
n--;
while (n)
{
e = myHeap.top();
myHeap.pop();
if (!vis[e.v2])
{
vis[e.v2] = 1;
n--;
apmEdges[e.v1].push_back({e.v2, e.w});
apmEdges[e.v2].push_back({e.v1, e.w});
len = lists[e.v2].size();
for (i = 0; i < len; i++)
myHeap.push({e.v2, lists[e.v2][i].v, lists[e.v2][i].w});
}
}
for (i = 0; i < cpn; i++)
vis[i] = 0;
myHeap = priority_queue<edge>();
}
void initLog2()
{
int logi = -1;
for (int i = 1; i < (NMAX << 1); i++)
{
if (1 << (logi + 1) == i)
logi++;
log2[i] = logi;
}
}
void buildEuler(int node, int currH)
{
int len = apmEdges[node].size();
vis[node] = 1;
for (int i = 0; i < len; i++)
{
if (!vis[apmEdges[node][i].v])
{
h[ind] = currH;
wes[ind] = apmEdges[node][i].w;
euler[ind] = node;
pos[node].push_back(ind);
ind++;
buildEuler(apmEdges[node][i].v, currH + 1);
}
}
h[ind] = currH;
wes[ind] = 0;
euler[ind] = node;
pos[node].push_back(ind);
ind++;
}
void initSptbls(int n)
{
for (int i = 0; i < n; i++)
spTblH[i][0] = i;
for (int i = 1; i <= log2[n]; i++)
{
int pow2 = 1 << i, smPow2 = pow2 >> 1;
for (int j = 0; j + pow2 - 1 < n; j++)
if (h[spTblH[j][i - 1]] < h[spTblH[j + smPow2][i - 1]])
spTblH[j][i] = spTblH[j][i - 1];
else
spTblH[j][i] = spTblH[j + smPow2][i - 1];
}
n--;
for (int i = 0; i < n; i++)
spTblW[i][0] = wes[i];
for (int i = 1; i <= log2[n]; i++)
{
int pow2 = 1 << i, smPow2 = pow2 >> 1;
for (int j = 0; j + pow2 - 1 < n; j++)
spTblW[j][i] = max(spTblW[j][i - 1], spTblW[j + smPow2][i - 1]);
}
}
int queryHeight(int lo, int hi)
{
if (lo > hi)
swap(lo, hi);
int len = hi - lo + 1;
if (h[spTblH[lo][log2[len]]] < h[spTblH[hi - (1 << log2[len]) + 1][log2[len]]])
return spTblH[lo][log2[len]];
return spTblH[hi - (1 << log2[len]) + 1][log2[len]];
}
int queryWeight(int lo, int hi)
{
if (lo > hi)
swap(lo, hi);
int len = hi - lo + 1;
return max(spTblW[lo][log2[len]], spTblW[hi - (1 << log2[len]) + 1][log2[len]]);
}
int getLCA(int v1, int v2)
{
return euler[queryHeight(pos[v1][0], pos[v2][0])];
}
int getMax(int v1, int v2)
{
int lca = getLCA(v1, v2), i, maxx = 0;
if (lca != v1)
{
i = -1;
while (pos[lca][i + 1] < pos[v1][0])
i++;
maxx = max(maxx, queryWeight(pos[lca][i], pos[v1][0] - 1));
}
if (lca != v2)
{
i = -1;
while (pos[lca][i + 1] < pos[v2][0])
i++;
maxx = max(maxx, queryWeight(pos[lca][i], pos[v2][0] - 1));
}
return maxx;
}