#include <fstream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
struct Edge{
int x, y, cost;
Edge(int x, int y, int cost) {
this->x = x;
this->y = y;
this->cost = cost;
}
bool operator < (const Edge a) const {
return cost < a.cost;
}
};
vector<Edge> edges;
vector< vector< pair<int, int> > > graph;
vector<int> pmd, parent, costParent, level;
vector< vector<int> > ancestors, ancestorsCost;
int getRoot(int node) {
int temp = node;
while (pmd[node] > 0)
node = pmd[node];
swap(temp, node);
while (node != temp) {
pmd[node] = temp;
node = pmd[node];
}
return temp;
}
void kruskal(vector<Edge> edges, int n, vector< vector< pair<int, int> > > &graph) {
sort(edges.begin(), edges.end());
pmd.clear();
pmd.resize(n + 1, -1);
for (unsigned int i = 0; i < edges.size(); ++i) {
int x = edges[i].x;
int y = edges[i].y;
int cost = edges[i].cost;
int rx = getRoot(x);
int ry = getRoot(y);
if (rx == ry)
continue;
if (pmd[rx] < pmd[ry]) {
pmd[rx] += pmd[ry];
pmd[ry] = rx;
}
else {
pmd[ry] += pmd[rx];
pmd[rx] = ry;
}
graph[x].push_back(make_pair(y, cost));
graph[y].push_back(make_pair(x, cost));
}
}
void dfs(int node, int par, int costPar, int lvl) {
parent[node] = par;
costParent[node] = costPar;
level[node] = lvl;
for (unsigned int i = 0; i < graph[node].size(); ++i) {
int adj = graph[node][i].first;
int cost = graph[node][i].second;
if (adj == par)
continue;
dfs(adj, node, cost, lvl + 1);
}
}
void compAncestors(int n, vector< vector<int> > &ancestors, vector< vector<int> > &ancestorsCost) {
for (int i = 1; i <= n; ++i) {
ancestors[0][i] = parent[i];
ancestorsCost[0][i] = costParent[i];
}
for (int i = 1; (1 << i) <= n; ++i) {
for (int j = 1; j <= n; ++j) {
ancestors[i][j] = ancestors[i - 1][ancestors[i - 1][j]];
ancestorsCost[i][j] = max(ancestorsCost[i - 1][ancestors[i - 1][j]], ancestorsCost[i - 1][j]);
}
}
}
int goUp(int &node, int lvl) {
int ret = 0;
for (int i = 16; i >= 0; --i) {
if (level[node] - lvl >= (1 << i)) {
ret = max(ret, ancestorsCost[i][node]);
node = ancestors[i][node];
}
}
return ret;
}
int query(int x, int y) {
int ret = 0;
for (int i = 16; i >= 0; --i) {
if (ancestors[i][x] != ancestors[i][y]) {
ret = max(ret, ancestorsCost[i][x]);
ret = max(ret, ancestorsCost[i][y]);
x = ancestors[i][x];
y = ancestors[i][y];
}
}
if (x != y) {
ret = max(ret, ancestors[0][x]);
ret = max(ret, ancestors[0][y]);
}
return ret;
}
int main() {
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");
int n, k, m;
fin >> n >> m >> k;
graph.resize(n + 1);
for (int i = 1; i <= n; ++i) {
int x, y, cost;
fin >> x >> y >> cost;
edges.push_back(Edge(x, y, cost));
}
kruskal(edges, n, graph);
parent.resize(n + 1, 0);
costParent.resize(n + 1, 0);
level.resize(n + 1, 0);
dfs(1, 0, 0, 1);
ancestors.resize(17, vector<int>(n + 1, 0));
ancestorsCost.resize(17, vector<int>(n + 1, 0));
compAncestors(n, ancestors, ancestorsCost);
for (; k; --k) {
int x, y;
fin >> x >> y;
int ans = 0;
if (level[x] > level[y])
ans = goUp(x, level[y]);
else if (level[x] < level[y])
ans = goUp(y, level[x]);
ans = max(ans, query(x, y));
fout << ans << '\n';
}
return 0;
}
//Trust me, I'm the Doctor!