#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,q,p[100001],depth[100001],f[100001][19];
//weight记录路径最小值,weight[i][j]表示从节点i到i走2^j步到达的父节点
//这一路径上的最小值
long long weight[100001][19];
bool st[100001];
//结构体存边
struct node{
int u,v,w;
bool operator <(const node& X)const{
return X.w<w;
}
}edge[300001];
//邻接表表示图
vector<pair<int,int>> g[100001];
//并查集
int find(int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
//LCA初始化,计算depth和weight和f数组
void lca_init(int r){
queue<int>q;
q.push(r);
depth[r]=1;
st[r]=true;
depth[0]=0;
while(!q.empty()){
int t=q.front();
q.pop();
for(auto i : g[t]){
int x=i.first,wi=i.second;
if(!st[x]){
st[x]=true;
q.push(x);
depth[x]=depth[t]+1;
f[x][0]=t;
weight[x][0]=wi;
for(int j=1;j<=17;j++){
f[x][j]=f[f[x][j-1]][j-1];
//计算weight[i][j],假设t=f[i][j-1],那么根据f[i][j]的计算方法->先计算先从i走2^(j-1)步到达t,
//再从t走2^(j-1)步到达父节点,那么weight数组就是取这两步的一个最小值即可
weight[x][j]=min(weight[x][j-1],weight[f[x][j-1]][j-1]);
}
}
}
}
}
//求两个节点a,b路径上的最小权值,就是在找最近公共祖先的路上用way数组更新答案
long long lca(int a,int b){
long long res=1e14;
if(depth[a]<depth[b])swap(a,b);
for(int i=17;i>=0;i--){
if(depth[f[a][i]]>=depth[b]){
res=min(res,weight[a][i]);
a=f[a][i];
}
}
if(a==b)return res;
for(int i=17;i>=0;i--){
if(f[a][i]!=f[b][i])
{
res=min(min(weight[a][i],weight[b][i]),res);
a=f[a][i];
b=f[b][i];
}
}
return min(res,min(weight[a][0],weight[b][0]));
}
int main(){
cin>>n>>m>>q;
for(int i=1;i<=n;i++)p[i]=i;
int u,v,w;
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
edge[i]={u,v,w};
}
sort(edge,edge+m);
//建立最大生成树
for(int i=0;i<m;i++){
int x=edge[i].u,y=edge[i].v,z=edge[i].w;
int px=find(x),py=find(y);
if(px!=py){
p[px]=py;
g[x].push_back({y,z});
g[y].push_back({x,z});
}
}
//找一个合法节点当根
for(int i=1;i<=n;i++)
if(g[i].size()>0){
lca_init(i);
break;
}
while(q--){
scanf("%d%d",&u,&v);
long long res=lca(u,v);
//res==0代表有一个节点不在不在生成树中
if(res>0)
printf("%d\n",res);
else printf("-1\n");
}
return 0;
}