#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream F("radiatie.in");
ofstream G("radiatie.out");
#define IT(type) vector<type>::iterator
#define cost first
#define x second.first
#define y second.second
#define lca first
#define ord second
const int Mmax = 15010;
const int Nmax = 30010;
typedef pair<int,int> Pair;
typedef pair<int,Pair> edge;
edge E[Mmax];
int N,M,Q,Gr[Nmax],Cost[Nmax];
vector<int> Cst[Nmax];
vector<int> V[Nmax];
vector<Pair> W[Nmax];
int Grup(int i)
{
if (Gr[i] == i) return i;
Gr[i] = Grup(Gr[i]);
return Gr[i];
}
void Union(int i,int j)
{ Gr[ Grup(i) ] = Grup(j) ; }
void Get_APM()
{
F>>N>>M>>Q;
for (int i=1;i<=N;++i)
Gr[i]=i;
for (int i=1;i<=M;++i)
F>>E[i].x>>E[i].y>>E[i].cost;
sort(E+1,E+M+1);
for (int i=1;i<=M;++i)
if ( Gr[Grup(E[i].x)] != Gr[Grup(E[i].y)] )
{
V[E[i].x].push_back(E[i].y);
Cst[E[i].x].push_back(E[i].cost);
V[E[i].y].push_back(E[i].x);
Cst[E[i].y].push_back(E[i].cost);
Union( E[i].x , E[i].y );
}
}
#undef x
#undef y
int L,Euler[Nmax<<2],First[Nmax],Last[Nmax],Lvl[Nmax];
int Dad[Nmax];
void Get_euler(int nod,int dad)
{
Euler[++L] = nod;
First[nod] = L;
Dad[nod] = dad;
Lvl[nod] = Lvl[dad]+1;
Last[nod] = L;
for (IT(int) it=V[nod].begin();it!=V[nod].end();++it)
if ( *it != dad )
{
Get_euler( *it,nod );
Euler[++L] = nod;
Last[nod] = L;
}
}
int A[Nmax<<4];
#define left ( nod*2 )
#define right ( nod*2+1 )
void Get(int nod,int& Min)
{
if ( Lvl[A[nod]] < Lvl[Min] ) Min = A[nod];
}
void Update(int nod,int st,int dr,int val,int poz)
{
if ( st == dr )
{
A[nod] = val;
return;
}
int mid = ( st + dr ) / 2;
if ( poz <= mid ) Update(left,st,mid,val,poz);
if ( poz > mid ) Update(right,mid+1,dr,val,poz);
Get(left,A[nod]);
Get(right,A[nod]);
}
int Min;
void Query(int nod,int st,int dr,int start,int stop)
{
if ( start <= st && dr <= stop )
{
Get(nod,Min);
return;
}
int mid = ( st + dr ) / 2;
if ( start <= mid ) Query(left,st,mid,start,stop);
if ( stop > mid ) Query(right,mid+1,dr,start,stop);
}
int LCA(int x,int y)
{
x = First[x];
y = First[y];
Min = 0;
Query(1,1,L,x,y);
return Min;
}
int Aint[Nmax<<2],Max;
void get(int nod,int& Max)
{
if ( Cost[Aint[nod]] > Cost[Max] )
Max = Aint[nod];
}
void update(int nod,int st,int dr,int val,int poz)
{
if ( st == dr )
{
Aint[nod] = val;
return;
}
int mid = ( st + dr ) / 2;
if ( poz <= mid ) update(left,st,mid,val,poz);
if ( poz > mid ) update(right,mid+1,dr,val,poz);
Aint[nod] = 0;
get(left,Aint[nod]);
get(right,Aint[nod]);
}
void query(int nod,int st,int dr,int start,int stop)
{
if ( start <= st && dr <= stop )
{
get(nod,Max);
return;
}
int mid = ( st + dr ) / 2;
if ( start <= mid ) query(left,st,mid,start,stop);
if ( stop > mid ) query(right,mid+1,dr,start,stop);
}
#define root 1
int lmax = 0;
void Find_cost(int nod,int now)
{
Cost[nod] = now;
lmax = max(lmax,Lvl[nod]);
for (unsigned int i=0;i<V[nod].size();++i)
if ( V[nod][i] != Dad[nod] )
Find_cost(V[nod][i],Cst[nod][i]);
}
int Sol[Nmax];
void Solve(int nod)
{
for (unsigned int i=0;i<W[nod].size();++i)
{
int st = W[nod][i].lca;
int where = W[nod][i].ord;
Max = 0 , query(1,1,lmax,Lvl[st],Lvl[nod]);
Sol[where] = max( Cost[Max] , Sol[where] );
}
for (unsigned int i=0;i<V[nod].size();++i)
{
int now = V[nod][i];
if ( now != Dad[nod] )
{
update(1,1,lmax,now,Lvl[nod]);
Solve(now);
update(1,1,lmax,0,Lvl[nod]);
}
}
}
int main()
{
Get_APM();
Lvl[0] = 0;
Get_euler(root,0);
Lvl[0] = 100010;
for (int i=1;i<=L;++i)
Update( 1,1,L,Euler[i],i );
for (int i=1,x,y;i<=Q;++i)
{
F>>x>>y;
int low = LCA(min(x,y),max(x,y));
W[x].push_back( make_pair( low,i ) );
W[y].push_back( make_pair( low,i ) );
}
Find_cost(root,0);
Solve(root);
for (int i=1;i<=Q;++i)
G<<Sol[i]<<'\n';
}