#include <bits/stdc++.h>
#define Nmax 15005
#define Mmax 30005
#define DIM 70000
using namespace std;
class Ifstream
{
private:
FILE *f;
char *buffer;
int cursor;
char read_ch()
{
if(++cursor==DIM)
{
cursor=0;
fread(buffer,1,DIM,f);
}
return buffer[cursor];
}
public:
Ifstream(const char *file_name)
{
f=fopen(file_name,"r");
buffer=new char[DIM]();
cursor=DIM-1;
}
Ifstream &operator >> (int &n)
{
char c;
n=0;
while(!isdigit(c=read_ch()) and c!='-');
int sgn=1;
if(c=='-') sgn=-1;
else n=c-'0';
while(isdigit(c=read_ch()))
n=10*n+c-'0';
n*=sgn;
return *this;
}
};
class Ofstream
{
private:
FILE *g;
char *buffer;
int cursor;
void write_ch(char ch)
{
if(cursor==DIM)
{
fwrite(buffer,1,DIM,g);
cursor=0;
}
buffer[cursor++]=ch;
}
public:
Ofstream(const char *file_name)
{
g=fopen(file_name,"w");
buffer=new char[DIM]();
cursor=0;
}
~Ofstream()
{
fwrite(buffer,1,cursor,g);
fclose(g);
}
Ofstream &operator << (int n)
{
if(n<10) write_ch(n+'0');
else
{
(*this)<<(n/10);
write_ch(n%10+'0');
}
return *this;
}
Ofstream &operator << (char c)
{
write_ch(c);
return *this;
}
};
Ifstream f("radiatie.in");
Ofstream g("radiatie.out");
struct edge
{
int l,r,val;
bool operator < (const edge &other) const
{
return this->val<other.val;
}
};
edge E[Mmax];
int t[Nmax],r[Nmax],v[Nmax],lvl[Nmax],Log2[Nmax<<1],poz[Nmax];
int rmq[20][Nmax<<1],M[20][Nmax],T[20][Nmax];
int n,m,Q,N;
list < pair <int,int> > tree[Nmax];
int Find(int x)
{
int root=x;
while(root!=t[root])
root=t[root];
int aux;
while(x!=t[x])
{
aux=t[x];
t[x]=root;
x=aux;
}
return root;
}
void Unite(int x, int y)
{
if(r[x]<r[y]) t[x]=y;
else t[y]=x;
if(r[x]==r[y]) r[x]++;
}
void Kruskal()
{
sort(E+1,E+m+1);
int i,x,y,nr;
for(i=1;i<=n;i++)
{
t[i]=i;
r[i]=1;
}
i=1;
nr=0;
while(nr<n-1)
{
x=Find(E[i].l);
y=Find(E[i].r);
if(x!=y)
{
Unite(x,y);
tree[E[i].l].push_back({E[i].r,E[i].val});
tree[E[i].r].push_back({E[i].l,E[i].val});
++nr;
}
++i;
}
}
void DFS(int x)
{
rmq[0][++N]=x;
poz[x]=N;
for(const auto &it:tree[x])
if(!lvl[it.first])
{
lvl[it.first]=lvl[x]+1;
T[0][it.first]=x;
M[0][it.first]=it.second;
DFS(it.first);
rmq[0][++N]=x;
}
}
inline int min_criterion(const int &x,const int &y)
{
if(lvl[x]<lvl[y]) return x;
return y;
}
void Compute_rmq()
{
int i,j;
Log2[2]=1;
for(i=3;i<=N;i++)
Log2[i]=Log2[i>>1]+1;
for(i=1;i<=Log2[N];i++)
for(j=1;j+(1<<(i-1))<=N;j++)
rmq[i][j]=min_criterion(rmq[i-1][j],rmq[i-1][j+(1<<(i-1))]);
}
void Compute_ancestors()
{
int i,j;
bool ok=true;
for(i=1;ok;i++)
{
ok=false;
for(j=1;j<=n;j++)
{
T[i][j]=T[i-1][T[i-1][j]];
M[i][j]=max(M[i-1][j],M[i-1][T[i-1][j]]);
if(T[i][j]) ok=true;
}
}
}
int LCA(int x, int y)
{
x=poz[x];
y=poz[y];
if(x>y) swap(x,y);
int k=Log2[y-x+1];
return min_criterion(rmq[k][x],rmq[k][y-(1<<k)+1]);
}
int get_max_val(int node, int lca)
{
int diff=lvl[node]-lvl[lca];
int ans=0;
while(diff)
{
ans=max(ans,M[Log2[diff]][node]);
node=T[Log2[diff]][node];
diff-=(1<<Log2[diff]);
}
return ans;
}
int main()
{
f>>n>>m>>Q;
int x,y,k,val1,val2,cnt;
for(cnt=1;cnt<=m;cnt++)
f>>E[cnt].l>>E[cnt].r>>E[cnt].val;
Kruskal();
lvl[1]=1;
DFS(1);
Compute_rmq();
Compute_ancestors();
while(Q--)
{
f>>x>>y;
k=LCA(x,y);
val1=get_max_val(x,k);
val2=get_max_val(y,k);
g<<max(val1,val2)<<'\n';
}
return 0;
}