#include <algorithm>
#include <fstream>
#include <cstdio>
#include <bitset>
#include <vector>
using namespace std;
const int BUFFER_SIZE=(1<<17);
class FileInput {
public:
FileInput() {}
FileInput(const char *filename) {
file = fopen(filename, "r");
fread(buffer, BUFFER_SIZE, 1, file);
cursor = 0;
}
inline FileInput & operator >> (int &n) {
while(buffer[cursor] == ' ' || buffer[cursor] == '\n') {
advance();
}
n = 0;
while(isdigit(buffer[cursor])) {
n = n * 10 + buffer[cursor] - '0';
advance();
}
return *this;
}
private:
FILE* file;
char buffer[BUFFER_SIZE];
int cursor;
inline void advance() {
++ cursor;
if(cursor == BUFFER_SIZE) {
cursor = 0;
fread(buffer, BUFFER_SIZE, 1, file);
}
}
};
FileInput fin("radiatie.in");
ofstream fout("radiatie.out");
const int N=15005, M=30005, LG=15;
struct mc
{
int x, y, c;
bool operator<(const mc &e) const
{
return c<e.x;
}
} MC[M];
class Tree{
private:
vector <vector<int>> G;
vector <int> h, l, first, rmq[LG], cost[LG], lg, f[LG], lvln;
int n, nr, ROOT;
void dfs(const int n, const int lvl)
{
lvln[n]=lvl;
h[++nr]=n;
l[nr]=lvl;
first[n]=nr;
for(auto p: G[n])
{
dfs(p, lvl+1);
h[++nr]=n;
l[nr]=lvl;
}
}
void build_rmq()
{
int i, j, y;
for(i=2;i<=nr;i++) lg[i]=lg[i>>1]+1;
for(i=1;i<=nr;i++) rmq[0][i]=i;
for(i=1;(1<<i)<nr;i++)
{
y=1<<(i-1);
for(j=1;j+(1<<i)<=nr;j++)
{
rmq[i][j]=rmq[i-1][j];
if(l[rmq[i-1][j+y]]<l[rmq[i][j]])
{
rmq[i][j]=rmq[i-1][j+y];
}
}
}
}
public:
Tree(){n=nr=0;}
Tree(const int _n)
{
n=_n;
G.resize(n+5);
first.resize(n+5);
l.resize(2*n+5);
lvln.resize(n+5);
h.resize(2*n+5);
lg.resize(2*n+5);
for(int i=0;i<LG;i++) rmq[i].resize(2*n+5), f[i].resize(n+5), cost[i].resize(n+5);
}
void resize(const int _n)
{
n=_n;
G.resize(n+5);
first.resize(n+5);
l.resize(2*n+5);
lvln.resize(n+5);
h.resize(2*n+5);
lg.resize(2*n+5);
for(int i=0;i<LG;i++) rmq[i].resize(2*n+5), f[i].resize(n+5), cost[i].resize(n+5);
}
void add_edge(const int x, const int y) {G[x].push_back(y);f[0][y]=x;}
void set_cost(const int x, const int y) {cost[0][x]=y;}
void set_root(const int x) {ROOT=x;}
void build_ancestors()
{
dfs(ROOT, 0);
build_rmq();
for(int i=1;i<15;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][f[i-1][j]];
cost[i][j]=max(cost[i-1][j], cost[i-1][f[i-1][j]]);
}
}
}
int lca(int x, int y)
{
int diff, ret;
x=first[x];
y=first[y];
if(x>y) swap(x, y);
diff=lg[y-x+1];
if(l[rmq[diff][x]]>l[rmq[diff][y-(1<<diff)+1]])
{
ret=rmq[diff][y-(1<<diff)+1];
}
else
{
ret=rmq[diff][x];
}
return h[ret];
}
int get_cost(int x, const int y)
{
int i, ret=0;
for(i=14;i>=0;i--)
{
if((1<<i)&y)
{
ret=max(ret, cost[i][x]);
x=f[i][x];
}
}
return ret;
}
int get_path(const int x, const int y)
{
int c1, c2, nod;
nod=lca(x, y);
c1=get_cost(x, lvln[x]-lvln[nod]);
c2=get_cost(y, lvln[y]-lvln[nod]);
return max(c1, c2);
}
};
Tree G;
int f[N];
int tfind(int x)
{
int y, p;
for(y=x;f[y]!=y;y=f[y]);
for(;f[x]!=x;x=p)
{
p=f[x];
f[x]=y;
}
return x;
}
int main()
{
int n, m, q, i, x, y;
fin>>n>>m>>q;
G.resize(n);
for(i=1;i<=m;i++) fin>>MC[i].x>>MC[i].y>>MC[i].c;
sort(MC+1, MC+m+1);
for(i=1;i<=n;i++) f[i]=i;
for(i=1;i<=m;i++)
{
x=tfind(MC[i].x);
y=tfind(MC[i].y);
if(x!=y)
{
f[x]=y;
G.add_edge(y, x);
G.set_cost(x, MC[i].c);
}
}
for(i=1;f[i]!=i;i++);
G.set_root(i);
G.build_ancestors();
while(q--)
{
fin>>x>>y;
fout<<G.get_path(x, y)<<"\n";
}
}