#include<stdio.h>
#define infile "radiatie.in"
#define outfile "radiatie.out"
#define nmax 15*1001
#define mmax 30*1001
struct lista
{
int n,p; //nodul si pozitia
int c; //costul
} l[mmax]; //lista arborelui
struct muchie
{
int x,y; //leaga nodul x cu nodul t
int c; //costul
} m[mmax]; //muchiile grafului
struct nod
{
int c; //componenta conexa din care face parte (cand facem kruskal), respectiv costul de la tata catre el cand raspunde-m la query-uri
int t; //tatal nodului (in arbore)
int h; //inaltimea la care se afla nodul in arbore (varful arborelui va fi nodul 1)
int p; //pozitia din lista
} n[nmax]; //nodurile
int nrl,nrm,nrn; //numarul pentru fiecare structura
int k; //numarul de intrebari
void add(int m, int x, int y, int c)
{ //adauga arcul (x,y) cu costul c
l[m].n=y; l[m].c=c; l[m].p=n[x].p; n[x].p=m;
}
void citire()
{
int i;
scanf("%d %d %d\n",&nrn,&nrm,&k);
for(i=1;i<=nrm;i++) //citim fiecare muchie
scanf("%d %d %d\n",&m[i].x,&m[i].y,&m[i].c); //muchia [x,y] cu costul c
}
int divide(int p, int q)
{
struct muchie x=m[p]; //muchia ce trebuie plasata corect
while(p<q)
{
while(p<q&&m[q].c>=x.c) q--; //cele din dreapta au costul mai mare
m[p]=m[q];
while(p<q&&m[p].c<=x.c) p++; //cele din stanga au costul mai mic
m[q]=m[p];
}
m[p]=x; //il plasam corect
return p; //ii returnam pozitia
}
void qsort(int p, int q)
{
int m=divide(p,q); //il plasam corect pe p
if(p<m-1) qsort(p,m-1); //partea stanga
if(m+1<q) qsort(m+1,q); //partea dreapta
}
void initializare()
{
int i;
for(i=1;i<=nrn;i++) n[i].c=i; //initil fiecare nod e singur in componenta conexa
}
void dfs(int x, int y)
{ //face o parcurgere din nodul x, si pune toate nodurile in componenta y
int p;
n[x].c=y;
for(p=n[x].p;p;p=l[p].p) //trecem la toti copii lui x
if(n[l[p].n].c!=y) //daca nu se afla in componenta y
dfs(l[p].n,y); //trebuie sa parcurgem
}
void kruskal()
{ //construim arborele partial de cost minim
int i=1; //prima muchie nefolosita
struct muchie x;
while((nrl/2)<nrn-1) //trebuie sa avem in lista N-1 muchii
{
x=m[i++]; //muchia pe care o putem folosi
if(n[x.x].c!=n[x.y].c) //daca muchia asta leaga doua puncte din componente conexe diferite
{
if(n[x.x].c<n[x.y].c)
dfs(x.y,n[x.x].c); //uneste cele doua componente conexe in componenta nodului x
else dfs(x.x,n[x.y].c); //uneste cele doua componente conexe in componenta nodului y
add(++nrl,x.x,x.y,x.c); //adaugam arcul (x,y) de cost c
add(++nrl,x.y,x.x,x.c); //adaugam arcum (y,x) de cost c
}
}
}
int inaltime(int x, int y, int c)
{ //calculam intaltimea nodului x, care il are pe tata pe y, cu muchie de cost c
int p,k=0;
n[x].t=y; //ii salvam tatal
n[x].c=c; //salvam costul
for(p=n[x].p;p;p=l[p].p) //trecem pe la toti copii
if(l[p].n!=y) //daca nu este insa-si tatal
{
k=inaltime(l[p].n,x,l[p].c); //aflam inaltimea acestui nod
if(n[x].h<=k) n[x].h=k+1; //avem o intaltime mai mare
}
if(k==0) n[x].h=1; //daca nu are inaltime sub :P (adica nu are fii)
return n[x].h; //returnam inaltimea
}
int query(int x, int y)
{
int m=0; //aici vom calcula lungimea maxima
while(x!=y)
{ //cat timp nu am ajuns intr-un stramos comun
if(n[x].h<n[y].h) //x are inaltimea mai mica....trebuie sa urce ;))
{
if(m<n[x].c) m=n[x].c; //avem cost mai mare
x=n[x].t; //ne ducem la tata;)
}
else //y are inaltimea mai mica...trebuie sa urce;))
{
if(m<n[y].c) m=n[y].c; //avem cost mai mare
y=n[y].t; //ne ducem la tata
}
}
return m; //returnam valoarea maxima din traseu ;))
}
int main()
{
int i,x,y;
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
citire(); //citim muchiile
initializare(); //facem padurea de arbori
qsort(1,nrm); //sortam muchiile
kruskal(); //construim arborele partial de cost minim
inaltime(1,0,0); //calculam inaltimile nodurilor in arbore (considerand nodul 1 tata)
for(i=1;i<=k;i++)
{
scanf("%d %d\n",&x,&y); //punctele intre care trebuie calculata muchia ;))
printf("%d\n",query(x,y)); //calculam si afisem lungimea muchiei maxime :P
}
fclose(stdin);
fclose(stdout);
return 0;
}