#include <stdio.h>
#define Smerenie 30000
#define Nadejde 15001
typedef struct {
int u, v, cost;
} cell;
typedef struct {
int v, cost, next;
} list;
int N, M, Q;
cell edge[Smerenie]; // muchiile citite, sortate dupa cost.
/** Caracteristicile nodurilor. **/
int d[Nadejde]; // adancimea nodului "u".
int pay[Nadejde]; // costul muchiei (u, father[u]) din APM.
int boss[Nadejde]; // seful nodului "u".
int father[Nadejde]; // tatal nodului "u" in APM.
/** Reprezentare APM. **/
int buff;
int adj[Nadejde]; // capetele listelor de adiacenta.
list l[Nadejde << 1]; // lista muchiilor din APM.
/** max(X, Y). **/
int MAX(int X, int Y) {
return X > Y ? X : Y;
}
/** Adauga-l pe "v" la lista de adiacenta a lui "u". **/
void addEdge(int u, int v, int cost) {
l[++buff].v = v;
l[buff].cost = cost;
l[buff].next = adj[u];
adj[u] = buff;
}
/** Sorteaza descrescator "edge". **/
void sort(int begin, int end) {
int b = begin, e = end;
int pivot = edge[(b + e) >> 1].cost;
while (b <= e) {
while (edge[b].cost < pivot) {
b++;
}
while (edge[e].cost > pivot) {
e--;
}
if (b <= e) {
cell tmp = edge[b];
edge[b++] = edge[e];
edge[e--] = tmp;
}
}
if (begin < e) {
sort(begin, e);
}
if (b < end) {
sort(b, end);
}
}
/** Initializeaza padurile disjuncte. **/
void init() {
int u;
for (u = 1; u <= N; u++) {
boss[u] = u;
}
}
/** Gaseste radacina nodului "u". **/
int find(int u) {
int r, tmp;
for (r = u; r != boss[r]; r = boss[r]);
for (; u != boss[u]; u = tmp) {
tmp = boss[u];
boss[u] = r;
}
return r;
}
/** Arbore partial de cost minim. **/
void apm() {
int i, ru, rv;
init();
sort(0, M - 1);
for (i = 0; i < M; i++) {
ru = find(edge[i].u);
rv = find(edge[i].v);
if (ru != rv) {
boss[rv] = ru;
addEdge(edge[i].u, edge[i].v, edge[i].cost);
addEdge(edge[i].v, edge[i].u, edge[i].cost);
}
}
}
/** Exploreaza APM-ul. **/
void dfs(int u, int dad, int cost) {
int pos;
pay[u] = cost;
father[u] = dad;
d[u] = d[dad] + 1;
for (pos = adj[u]; pos; pos = l[pos].next) {
if (l[pos].v != dad) {
dfs(l[pos].v, u, l[pos].cost);
}
}
}
/** Urca nodul "u" cu "level" nivele. **/
int climb(int *u, int level) {
int result = 0;
while (level--) {
result = MAX(result, pay[*u]);
(*u) = father[*u];
}
return result;
}
int main(void) {
int i, u, v, diff, result;
FILE *f = fopen("radiatie.in", "r");
/* Citirea datelor. */
fscanf(f, "%d %d %d", &N, &M, &Q);
for (i = 0; i < M; i++) {
fscanf(f, "%d %d %d", &edge[i].u, &edge[i].v, &edge[i].cost);
}
/* Calcularea solutiei. */
apm();
dfs(1, 0, 0);
/* Raspunde la intrebari. */
freopen("radiatie.out", "w", stdout);
while (Q--) {
fscanf(f, "%d %d", &u, &v);
/* Adu nodurile pe acelasi nivel. */
diff = d[u] - d[v];
if (diff < 0) {
result = climb(&v, -diff);
} else {
result = climb(&u, diff);
}
while (u != v) {
result = MAX(result, MAX(pay[u], pay[v]));
u = father[u];
v = father[v];
}
fprintf(stdout, "%d\n", result);
}
fclose(f);
fclose(stdout);
/// Multumim Doamne!
puts("Doamne ajuta!");
return 0;
}