#include <bits/stdc++.h>
using namespace std;
const int N_MAX = 15005, LOG_N = 13, M_MAX = 30005, K_MAX = 15005;
int N, M, K, logN;
int timer;
int tin[2 * N_MAX], tout[2 * N_MAX];
int T[N_MAX][LOG_N];
int Max[N_MAX][LOG_N];
bitset<N_MAX> visited;
struct FixedEdge
{
int v1, v2, c;
inline bool operator< (const FixedEdge& rhs) const
{
return c < rhs.c;
}
};
struct Edge
{
int v, c;
Edge(int _v, int _c) :
v(_v), c(_c) { }
};
FixedEdge Edges[M_MAX];
vector<Edge> G[N_MAX];
struct DisjointSetUnion
{
int T[N_MAX];
int Size[N_MAX];
int N;
inline void MakeSet(int v)
{
T[v] = v;
Size[v] = 1;
}
int FindSet(int v)
{
if(T[v] != v)
T[v] = FindSet(T[v]);
return T[v];
}
bool AreDisjoint(int a, int b)
{
return FindSet(a) != FindSet(b);
}
void Union(int a, int b)
{
a = FindSet(a);
b = FindSet(b);
if(a == b)
return;
if(Size[a] < Size[b])
swap(a, b);
T[b] = a;
Size[a] += Size[b];
}
void Build(int N)
{
this->N = N;
for(int i = 1; i <= N; i++)
MakeSet(i);
}
} dsu;
void SetInput(string name)
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
(void)!freopen((name + ".in").c_str(), "r", stdin);
(void)!freopen((name + ".out").c_str(), "w", stdout);
}
void ReadInput()
{
cin >> N >> M >> K;
for(int i = 0; i < M; i++)
cin >> Edges[i].v1 >> Edges[i].v2 >> Edges[i].c;
}
void Kruskal()
{
sort(Edges, Edges + M);
for(int i = 0; i < M; i++)
{
auto [v1, v2, c] = Edges[i];
if(dsu.AreDisjoint(v1, v2))
{
dsu.Union(v1, v2);
G[v1].emplace_back(v2, c);
G[v2].emplace_back(v1, c);
}
}
}
void DFS(int v, int p)
{
visited[v] = 1;
tin[v] = ++timer;
T[v][0] = p;
for(int i = 1; i <= logN; i++)
{
T[v][i] = T[T[v][i-1]][i-1];
Max[v][i] = max(Max[v][i-1], Max[T[v][i-1]][i-1]);
}
for(auto& [u, cost] : G[v])
if(u != p)
{
Max[u][0] = cost;
DFS(u, v);
}
tout[v] = ++timer;
}
inline bool IsAncestor(int& u, int& v)
{
return tin[u] <= tin[v] && tout[u] >= tout[v];
}
int LCA(int u, int v)
{
if(IsAncestor(u, v))
return u;
if(IsAncestor(v, u))
return v;
for(int i = logN; i >= 0; i--)
if(not IsAncestor(T[u][i], v))
u = T[u][i];
return T[u][0];
}
void BuildLCA()
{
timer = 0;
logN = ceil(log2(N));
for(int i = 1; i <= N; i++)
if(not visited[i])
{
Max[i][0] = 0;
DFS(i, i);
}
}
int FindMaxInPath(int v, int p)
{
if(v == p)
return 0;
if(not IsAncestor(p, v))
return 0;
int ans = 0;
for(int i = logN; i >= 0; i--)
if(not IsAncestor(T[v][i], p))
{
ans = max(ans, Max[v][i]);
v = T[v][i];
}
ans = max(ans, Max[v][0]);
return ans;
}
void AnswerQueries()
{
for(int i = 0, u, v, lca, ans; i < K; i++)
{
cin >> u >> v;
if(dsu.AreDisjoint(u, v))
{
cout << "0\n";
continue;
}
lca = LCA(u, v);
ans = FindMaxInPath(u, lca);
ans = max(ans, FindMaxInPath(v, lca));
cout << ans << '\n';
}
}
int main()
{
SetInput("radiatie");
ReadInput();
dsu.Build(N);
Kruskal();
BuildLCA();
AnswerQueries();
return 0;
}