#include <fstream>
#include <vector>
#include <cmath>
#define NMAX 15100
#define MMAX 30100
using namespace std;
ifstream fin("radiatie.in");
ofstream fout("radiatie.out");
int n,nr,m,cx,cy;
int k;
inline int maxim(int a,int b)
{
if(a>b)
return a;
return b;
}
inline void swape(int& a,int& b)
{
int aux=a;
a=b;
b=aux;
}
int h[MMAX];
int tata[MMAX];
struct ele{int y,cost;};
vector<ele> g[NMAX];
int p[NMAX][30];
int coin[NMAX][30];
int level[NMAX];
void dfs(int start,int nivel);
ele tati[NMAX];
bool da[NMAX];
int Find(int x);
void Union (int x,int y);
int caut(int x,int y);
struct muchie{
int x,y,cost;
friend bool operator < (muchie a,muchie b);
friend bool operator <= (muchie a,muchie b);
friend bool operator >= (muchie a,muchie b);
friend bool operator > (muchie a,muchie b);
};
muchie H[MMAX],a[NMAX];
bool operator < (muchie a,muchie b)
{
return a.cost<b.cost;
}
bool operator <= (muchie a,muchie b)
{
return a.cost<=b.cost;
}
bool operator >= (muchie a,muchie b)
{
return a.cost>=b.cost;
}
bool operator > (muchie a,muchie b)
{
return a.cost>b.cost;
}
int nrsel,costtotal;muchie mmin;
void creare();
void afisare(int n, muchie H[]);
void inserare(int &n,muchie H[], muchie x);
void combinare(int n,muchie H[],int poz); ///poz=pozitia radacinii
muchie extragemin(int &n , muchie H[]);
void heapsort();
int main()
{//citire(n,H);
int i,j;
int x,y,m1,m2,lca,lo;
creare();
while(nrsel<n-1)
{
mmin=extragemin(m,H);
cx=Find(mmin.x);
cy=Find(mmin.y);
if(cx!=cy)
{
nrsel++;
costtotal+=mmin.cost;
a[nrsel]=mmin;
Union(cx,cy);
}
}
for(i=1;i<=n-1;i++)
g[a[i].x].push_back({a[i].y,a[i].cost}),g[a[i].y].push_back({a[i].x,a[i].cost});
dfs(1,1);
for(j=0;j<=log2(n);j++)
for(i=1;i<=n;i++)
if(!j)
p[i][j]=tati[i].y,coin[i][j]=tati[i].cost;
else
p[i][j]=p[p[i][j-1]][j-1],coin[i][j]=maxim(coin[i][j-1],coin[p[i][j-1]][j-1]);
for(i=1;i<=k;i++)
{
fin>>x>>y;
fout<<caut(x,y)<<'\n';
}
}
void afisare(int n, int H[] )
{
int i;
for(i=1;i<=n;i++)
fout<<H[i]<< " ";
fout.close();
}
void inserare(int &n,int H[], int x)
{int fiu, tata;
fiu=++n; tata=fiu/2;
///fiu= pozitia pe care vreau sa il pun pe x
while(tata && H[tata]>x)
{
H[fiu]=H[tata];
fiu=tata;
tata=fiu/2;
}
H[fiu]=x;
}
void combinare(int n,muchie H[],int poz)
{int fiu,tata;
muchie x=H[poz];
tata=poz;fiu=2*tata; ///fiul stang
while(fiu<=n)
{
if(fiu+1<=n && H[fiu+1]<H[fiu]) fiu++;
///fiul e min deci daca il pun in locul tatalui se respecta ordinea
if(x <= H[fiu]) break; ///daca emai mic decat minim e aranjat, nu fac nik
H[tata]=H[fiu];
tata=fiu;
fiu=2*tata;
}
H[tata]=x;
}
void creare()
{int i;
fin>>n>>m>>k;
for(i=1;i<=m;i++) fin>>H[i].x>>H[i].y>>H[i].cost;
for(i=m/2;i>0;i--) ///fiecare element de la care poate porni un graf(trebuie sa aiba fiu)
combinare(m,H,i);
}
muchie extragemin(int &n , muchie H[])
{muchie minim;
minim=H[1];///iau elementul si resortez (ala era cel mai mic)
H[1]=H[n--];
combinare(n,H,1);
return minim;
}
int Find(int x)
{
int rad=x;int aux;
while(tata[rad])
rad=tata[rad];
while(tata[x])
{ aux=tata[x];
tata[x]=rad;
x=aux;
}
return rad;
}
void Union(int x,int y)
{ if(h[x]<h[y])
tata[x]=y;
else
{tata[y]=x;if(h[x]==h[y])h[x]++;}
}
void dfs(int start,int nivel)
{
int i;
da[start]=1;
level[start]=nivel;
for(i=0;i<g[start].size();i++)
if(!da[g[start][i].y])
tati[g[start][i].y].y=start,tati[g[start][i].y].cost=g[start][i].cost,dfs(g[start][i].y,nivel+1);
}
int caut(int x,int y)
{int i,sol;
if(level[x]>level[y])
swape(x,y);
sol=tati[y].cost;
for(i=log2(n);i>=0;i--)
if(level[y]-(1<<i)>=level[x])
sol=maxim(sol,coin[y][i]),y=p[y][i];
if(x==y)
return sol;
for(i=log2(n);i>=0;i--)
if(p[x][i]>0&&p[x][i]!=p[y][i])
sol=maxim(sol,coin[y][i]),sol=maxim(sol,coin[x][i]),x=p[x][i],y=p[y][i];
return sol;
}