Rt
#include <bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define ldb long double
#define db double
#define endl '\n'
using namespace std;
namespace OI {
template <typename T>
T read() {
T x = 0, f = 1;
int ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
template <typename TE>
void write(TE x) {
TE sta[35];
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) putchar(sta[--top] + '0');
}
string read_with_string() {
string s = "";
char ch = getchar();
while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {
s += ch;
ch = getchar();
}
return s;
}
void write_with_string(string s) {
for (int i = 0; i < s.size(); i++) putchar(s[i]);
}
}
using namespace OI;
const int N = 1e5 + 10;
int n, m;
struct edge {
int x, y;
int val;
bool operator < (const edge &b) const {
return val < b.val;
}
} e[N];
vector<int> g[N];
int val[N * 2];
int f[N], fa[N];
int Q;
int root;
int dep[N], vis[N];
class dsu {
private:
int f[N];
public:
void clear() {
// memset(f, 0, sizeof f);
for (int i = 1; i <= n; i++) f[i] = 0;
}
void init(int n) {
for (int i = 1; i <= n; i++) f[i] = i;
}
int find(int x) {
return (f[x] == x ? x : f[x] = find(f[x]));
}
bool check(int x, int y) {
int rx = find(x), ry = find(y);
if (rx == ry) return false;
return true;
}
void add(int x, int y) {
if (check(x, y)) {
int rx = find(x), ry = find(y);
f[rx] = ry;
}
}
};
dsu d, ds;
class Debug {
private:
public:
void debug_cgs_g() {
for (int i = 1; i <= n; i++) {
cout << i << " : \n";
for (int j = 0; j < g[i].size(); j++)
cout << g[i][j] << " ";
cout << endl;
}
}
void debug_cgs_val() {
cout << "val : \n";
for (int i = 1; i <= n; i++) cout << i << " ";
cout << endl;
for (int i = 1; i <= n; i++) cout << val[i] << " ";
cout << endl;
}
void debug_fa() {
cout << "fa : \n";
for (int i = 1; i <= n; i++) cout << i << " ";
cout << endl;
for (int i = 1; i <= n; i++) cout << fa[i] << " ";
cout << endl;
}
void debug_e() {
cout << "e : \n";
cout << " ";
for (int i = 1; i <= m; i++) printf("%6lld", i);
cout << "\nx : ";
for (int i = 1; i <= m; i++) printf("%6lld", e[i].x);
cout << "\ny : ";
for (int i = 1; i <= m; i++) printf("%6lld", e[i].y);
cout << "\nval : ";
for (int i = 1; i <= m; i++) printf("%6lld", e[i].val);
cout << endl;
}
void debug_dep() {
cout << "dep : \n";
for (int i = 1; i <= n; i++) cout << i << " ";
cout << endl;
for (int i = 1; i <= n; i++) cout << dep[i] << " ";
cout << endl;
}
};
Debug debug;
class LCA {
private:
int dp[N][20];
public:
void clear() {
// memset(dp, 0, sizeof dp);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= log2(n); j++)
dp[i][j] = 0;
}
void init() {
for (int i = 1; i <= n; i++) dp[i][0] = fa[i];
for (int j = 1; j <= log2(n); j++)
for (int i = 1; i <= n; i++)
dp[i][j] = dp[dp[i][j - 1]][j - 1];
}
int ask(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i = 0, len = dep[x] - dep[y]; i <= log2(n); i++, len >>= 1) if (len & 1) x = dp[x][i];
if (x == y) return x;
for (int i = log2(n); i >= 0; i--) {
if (dp[x][i] == dp[y][i]) continue;
x = dp[x][i];
y = dp[y][i];
}
return dp[x][0];
}
};
LCA lca;
queue<pair<int, int> > q;
class SegmentTree {
private:
struct node {
int l, r;
int max_dep, min_dep;
int max_id, min_id;
} tree[N * 4];
pair<int, int> ans;
pair<int, int> answer;
public:
void clear() {
// memset(tree, 0, sizeof tree);
for (int i = 1; i <= n * 4; i++) tree[i] = {0, 0, 0, 0, 0, 0};
ans.first = INT_MIN, ans.second = INT_MAX;
}
void push_up(int k) {
// tree[k].max_dep = max(tree[k * 2].max_dep, tree[k * 2 + 1].max_dep);
// tree[k].min_dep = min(tree[k * 2].min_dep, tree[k * 2 + 1].min_dep);
if (tree[k * 2].max_dep > tree[k * 2 + 1].max_dep) {
tree[k].max_dep = tree[k * 2].max_dep;
tree[k].max_id = tree[k * 2].max_id;
} else {
tree[k].max_dep = tree[k * 2 + 1].max_dep;
tree[k].max_id = tree[k * 2 + 1].max_id;
}
if (tree[k * 2].min_dep < tree[k * 2 + 1].min_dep) {
tree[k].min_dep = tree[k * 2].min_dep;
tree[k].min_id = tree[k * 2].min_id;
} else {
tree[k].min_dep = tree[k * 2 + 1].min_dep;
tree[k].min_id = tree[k * 2 + 1].min_id;
}
}
void Build(int k, int l, int r) {
tree[k].l = l, tree[k].r = r;
if (l == r) {
tree[k].max_dep = tree[k].min_dep = dep[l];
tree[k].max_id = tree[k].min_id = l;
return ;
}
int mid = (l + r) >> 1;
Build(k * 2, l, mid);
Build(k * 2 + 1, mid + 1, r);
push_up(k);
}
void Ask(int k, int l, int r) {
if (r < tree[k].l || l > tree[k].r) return ;
// cout << tree[k].l << " " << tree[k].r << " @@@@@@@@@@" << endl;
if (l <= tree[k].l && tree[k].r <= r) {
// ans.first = max(ans.first, tree[k].max_dep);
// ans.second = min(ans.second, tree[k].min_dep);
if (tree[k].max_dep > ans.first) {
ans.first = tree[k].max_dep;
answer.first = tree[k].max_id;
// cout << "answer.first = " << tree[k].max_id << endl;
} else if (tree[k].max_dep == ans.first && answer.first == answer.second && answer.first != tree[k].max_id) {
answer.first = tree[k].max_id;
// cout << "answer.first = " << tree[k].max_id << endl;
}
if (tree[k].min_dep < ans.second) {
ans.second = tree[k].min_dep;
answer.second = tree[k].min_id;
// cout << "answer.second = " << tree[k].min_id << endl;
} else if (tree[k].min_dep == ans.second && answer.first == answer.second && answer.second != tree[k].min_id) {
answer.second = tree[k].min_id;
// cout << "answer.second = " << tree[k].min_id << endl;
}
return ;
}
Ask(k * 2, l, r);
Ask(k * 2 + 1, l, r);
}
pair<int, int> solution(int l, int r) {
ans.first = INT_MIN, ans.second = INT_MAX;
Ask(1, l, r);
// cout << ans.first << " " << ans.second << " @@@@\n";
// cout << answer.first << " " << answer.second << " $$$$\n";
return answer;
}
};
SegmentTree SegTree;
void Clear() {
d.clear();
ds.clear();
lca.clear();
SegTree.clear();
// memset(f, 0, sizeof f);
for (int i = 1; i <= n; i++) f[i] = 0;
// memset(fa, 0, sizeof fa);
for (int i = 1; i <= n; i++) fa[i] = 0;
// memset(val, 0, sizeof val);
for (int i = 1; i <= n; i++) val[i] = 0;
// memset(dep, 0, sizeof dep);
for (int i = 1; i <= n; i++) dep[i] = 0;
// memset(vis, 0, sizeof vis);
for (int i = 1; i <= n; i++) vis[i] = 0;
while (!q.empty()) q.pop();
for (int i = 1; i <= n; i++) g[i].clear();
}
void Solve() {
Clear();
// cin >> n >> m >> Q;
n = read<int>(), m = read<int>(), Q = read<int>();
for (int i = 1; i <= n; i++) f[i] = i;
d.init(n), ds.init(n * 2);
for (int i = 1; i <= m; i++) {
e[i].x = read<int>(), e[i].y = read<int>();
e[i].val = i;
}
sort(e + 1, e + m + 1);
for (int i = 1; i <= m; i++) {
int x = e[i].x, y = e[i].y;
if (d.check(x, y)) {
n++;
val[n] = e[i].val;
g[n].push_back(ds.find(x));
g[n].push_back(ds.find(y));
d.add(x, y);
ds.add(x, n);
ds.add(y, n);
}
}
for (int i = n; i >= 1; i--) {
if (!vis[i]) {
root = i;
q.push(make_pair(root, 1));
while (!q.empty()) {
pair<int, int> u = q.front();
q.pop();
vis[u.first] = 1;
dep[u.first] = u.second;
for (int i = 0; i < g[u.first].size(); i++) {
int v = g[u.first][i];
if (!vis[v]) {
q.push(make_pair(v, u.second + 1));
fa[v] = u.first;
}
}
}
}
}
// debug.debug_dep();
SegTree.Build(1, 1, (n + 1) / 2);
lca.init();
while (Q--) {
int x, y;
x = read<int>(), y = read<int>();
if (x == y) {
printf("0 ");
continue;
}
if (dep[x] == dep[y] && fa[x] == fa[y] && abs(x - y) == 1) {
printf("%lld ", val[fa[x]]);
continue;
}
pair<int, int> t = SegTree.solution(x, y);
// cout << t.first << " " << t.second << " @@@@@" << endl;
printf("%lld ", val[lca.ask(t.first, t.second)]);
}
printf("\n");
// cout << "---------------------------\n";
}
signed main() {
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// freopen(".in", "r", stdin);
// freopen(".ans", "w", stdout);
int t = 1;
cin >> t;
while (t--) Solve();
return 0;
}
/*
1
2 1 2
1 2
1 1
1 2
*/