# include <stdio.h>
# include <stdlib.h>
const long int
MAXM=30000,
MAXK=15000,
MAXN=15000;
typedef struct MUCHIE {long int a,b,cost;};
struct {long int a,b,answ;} task[MAXK+1];
MUCHIE muc[MAXM+1],heap[MAXM+1];
long int n,m,k,heaplen,tata[MAXN+1],listlen,rad,chainlen;
struct {long int next,info;} ladiac[MAXN+1];
typedef struct NOD {long int prim,ultim,tata,cost,niv;};
typedef struct NOD_ARB_DINT {NOD_ARB_DINT *drta,*stga; long int lca;};
NOD_ARB_DINT *raddint;
NOD nod[MAXN+1];
long int chain[3*MAXN+1],first[MAXN+1];
//////////////////////////////////////////////////
// HEAP INTERFACE
//////////////////////////////////////////////////
void float_heap(long int i)
{
MUCHIE aux;
while (i!=1&&heap[i/2].cost>heap[i].cost)
{
aux=heap[i/2];
heap[i/2]=heap[i];
heap[i]=aux;
i/=2;
}
}
void create_heap()
{
long int i;
for (i=1;i<=m;i++)
{
heap[++heaplen]=muc[i];
float_heap(heaplen);
}
}
void submerge_heap(long int i)
{
MUCHIE aux;
long int min=i;
if (2*i<=heaplen&&heap[2*i].cost<heap[min].cost) min=2*i;
if (2*i+1<=heaplen&&heap[2*i+1].cost<heap[min].cost) min=2*i+1;
if (min!=i)
{
aux=heap[i];
heap[i]=heap[min];
heap[min]=aux;
submerge_heap(min);
}
}
//////////////////////////////////////////////////
// DISJOINT SET STRUCTURE INTERFACE
//////////////////////////////////////////////////
void init_set()
{
long int i;
for (i=1;i<=n;i++) tata[i]=i;
}
long int find_set(long int ord)
{
long int s=ord;
while (tata[ord]!=ord) ord=tata[ord];
tata[s]=ord;
return ord;
}
void merge(long int o1, long int o2) {tata[o2]=o1;}
//////////////////////////////////////////////////
// CREATE MINIMUM SPAN TREE
//////////////////////////////////////////////////
void kruskall()
{
create_heap();
long int i;
for (i=1;i<=n-1;i++)
{
while (find_set(heap[1].a)==find_set(heap[1].b))
{
heap[1]=heap[heaplen];
heaplen--;
submerge_heap(1);
}
muc[i]=heap[1];
merge(find_set(heap[1].a),find_set(heap[1].b));
heap[1]=heap[heaplen];
heaplen--;
submerge_heap(1);
}
}
void add_node(long int loc, long int val, long int cost)
{
ladiac[++listlen].info=val;
ladiac[listlen].next=0;
nod[val].cost=cost;
if (nod[loc].prim==0)
{
nod[loc].prim=listlen;
nod[loc].ultim=listlen;
}
else
{
ladiac[nod[loc].ultim].next=listlen;
nod[loc].ultim=listlen;
}
}
void create_tree_structure()
{
long int i;int sel[MAXN+1]={0};
for (i=1;i<=n-1;i++)
{
if (sel[muc[i].b]==0)
add_node(muc[i].a,muc[i].b,muc[i].cost);
else add_node(muc[i].b,muc[i].a,muc[i].cost);
if (sel[muc[i].a]==sel[muc[i].b]&&sel[muc[i].a]==0) rad=muc[i].a;
sel[muc[i].a]=1;
sel[muc[i].b]=1;
}
}
//////////////////////////////////////////////////
// CREATE CHAIN AND PERFORM DFS ON TREE
//////////////////////////////////////////////////
void df_and_create_chain(long int node, long int tata, long int niv)
{
nod[node].niv=niv;
nod[node].tata=tata;
chain[++chainlen]=node;
long int p=nod[node].prim;
while (p!=0)
{
df_and_create_chain(ladiac[p].info,node,niv+1);
p=ladiac[p].next;
chain[++chainlen]=node;
}
}
void prepare_nodes()
{
long int i;
for (i=1;i<=chainlen;i++)
if (first[chain[i]]==0) first[chain[i]]=i;
}
//////////////////////////////////////////////////
// SEGMENT TREE INTERFACE
//////////////////////////////////////////////////
void aloca_arb_dint(NOD_ARB_DINT *p, long int li, long int lf)
{
NOD_ARB_DINT *q;
long int mij=(li+lf)/2;
if (li!=lf)
{
q=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
(*q).lca=0;
(*p).stga=q;
aloca_arb_dint(q,li,mij);
q=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
(*q).lca=0;
(*p).drta=q;
aloca_arb_dint(q,mij+1,lf);
}
else
{
(*p).drta=NULL;
(*p).stga=NULL;
}
}
void update(NOD_ARB_DINT *p, long int a, long int li, long int lf)
{
long int mij=(li+lf)/2;
if ((*p).lca==0||nod[chain[a]].niv<nod[(*p).lca].niv)
{
(*p).lca=chain[a];
}
if (a!=li||a!=lf)
if (a<=mij)
update((*p).stga,a,li,mij);
else
update((*p).drta,a,mij+1,lf);
}
void create_segment_tree()
{
long int i;
for (i=1;i<=chainlen;i++)
update(raddint,i,1,chainlen);
}
long int lca(NOD_ARB_DINT *p,long int a, long int b, long int li, long int lf)
{
long int mij=(li+lf)/2;
if (a<=li&&lf<=b) return (*p).lca;
long int w=0,ww=0;
if (a<=mij) w=lca((*p).stga,a,b,li,mij);
if (b>mij) ww=lca((*p).drta,a,b,mij+1,lf);
if (w!=0&&ww!=0)
{
if (nod[w].niv>nod[ww].niv) w=ww;
}
else if (w==0) w=ww;
return w;
}
void print_tree(NOD_ARB_DINT *p, long int li, long int lf)
{
long int mij=(li+lf)/2;
printf("%ld %ld : %ld\n",li,lf,(*p).lca);
if ((*p).stga) print_tree((*p).stga,li,mij);
if ((*p).drta) print_tree((*p).drta,mij+1,lf);
}
//////////////////////////////////////////////////
// MAIN SOLVE FUNCTION
//////////////////////////////////////////////////
long int find_max(long int a, long int b)
{
long int sol=0;
if (a!=b)
{
sol+=nod[a].cost;
a=nod[a].tata;
}
return sol;
}
void solve()
{
long int i,aux,answ1,answ2;
for (i=1;i<=k;i++)
{
aux=lca(raddint,first[task[i].a],first[task[i].b],1,chainlen);
answ1=find_max(task[i].a,aux);
answ2=find_max(task[i].b,aux);
if (answ1>answ2) task[i].answ=answ1;
else task[i].answ=answ2;
}
}
//////////////////////////////////////////////////
// MAIN AND MAIN PROGRAM'S INTERFACE
//////////////////////////////////////////////////
void citire()
{
FILE *f=fopen("radiatie.in","r");
fscanf(f,"%ld%ld%ld",&n,&m,&k);
long int i;
for (i=1;i<=m;i++)
fscanf(f,"%ld%ld%ld",&muc[i].a,&muc[i].b,&muc[i].cost);
for (i=1;i<=k;i++)
fscanf(f,"%ld%ld",&task[i].a,&task[i].b);
fclose(f);
}
void scrie()
{
FILE *g=fopen("radiatie.out","w");
long int i;
for (i=1;i<=k;i++)
fprintf(g,"%ld\n",task[i].answ);
fcloseall();
}
int main()
{
citire();
init_set();
kruskall();
create_tree_structure();
df_and_create_chain(rad,0,1);
raddint=(NOD_ARB_DINT*) malloc (sizeof(NOD_ARB_DINT));
(*raddint).lca=0;
aloca_arb_dint(raddint,1,chainlen);
/*create_segment_tree();
prepare_nodes();
solve();
print_tree(raddint,1,chainlen);
scrie();*/
return 0;
}