#include using namespace std; struct UnWeightedGraph { struct Edge { int to; Edge(int to) : to(to) {} }; vector> edges; int n; UnWeightedGraph(int n) : n(n) { edges.assign(n, vector()); } void add_edge(int v, int u) { edges[v].emplace_back(u); } vector &operator[](int x) { return edges[x]; } }; template struct LowLink { using A = vector; using B = vector>; Graph &g; int n; vector seen; vector ord, low; A articulation; B bridge; LowLink(Graph &g) : g(g), n(g.n) {} void dfs(int v, int p, int &k) { seen[v] = true; ord[v] = k++; low[v] = ord[v]; bool is = false; int cnt = 0; for (auto e : g[v]) { int u = e.to; if (seen[u]) { if (u != p) low[v] = min(low[v], ord[u]); continue; } cnt++; dfs(u, v, k); low[v] = min(low[v], low[u]); if (p != -1 && ord[v] <= low[u]) is = true; if (ord[v] < low[u]) bridge.emplace_back(minmax(v, u)); } if (p == -1 && cnt > 1) is = true; if (is) articulation.push_back(v); } pair build() { seen.assign(n, false); ord.assign(n, 0); low.assign(n, 0); articulation.clear(); bridge.clear(); int k = 0; dfs(0, -1, k); return pair(articulation, bridge); } pair operator()() { return build(); } }; template struct TwoEdgeConnectedComponent { using B = vector>; Graph &g; int n; vector seen; vector group; set> b; TwoEdgeConnectedComponent(Graph &g) : g(g), n(g.n), group(n) {} void dfs(int v, int p, int k) { seen[v] = true; group[v] = k; for (auto e : g[v]) { int u = e.to; if (u == p) continue; if (seen[u]) continue; if (b.find(minmax(v, u)) != b.end()) continue; dfs(u, v, k); } } vector decompose(B bridge) { seen.assign(n, false); b.clear(); b.insert(bridge.begin(), bridge.end()); int k = 0; for (int i = 0; i < n; i++) { if (seen[i]) continue; dfs(i, -1, k++); } return group; } vector operator()(B bridge) { return decompose(bridge); } }; template struct SegmentTree { using F = function; vector v; F f; T e; int n; SegmentTree(int size, F f, T e) : f(f), e(e) { n = 1; while (n < size) n <<= 1; v.resize(n * 2, e); } void set(int k, T x) { v[k + n] = x; } void build() { for (int i = n - 1; i > 0; i--) { v[i] = f(v[i * 2 + 0], v[i * 2 + 1]); } } void update(int k, T x) { v[k += n] = x; while (k >>= 1) v[k] = f(v[k * 2 + 0], v[k * 2 + 1]); } T query(int a, int b) { T l = e, r = e; for (a += n, b += n; a < b; a >>= 1, b >>= 1) { if (a & 1) l = f(l, v[a++]); if (b & 1) r = f(v[--b], r); } return f(l, r); } }; template struct HeavyLightDecomposition { Graph &g; int n; vector par; vector next; vector vid; vector head; HeavyLightDecomposition(Graph &g) : g(g), n(g.n), par(n), next(n, -1), vid(n), head(n) {} int dfs(int v = 0, int p = -1) { par[v] = p; int mx = 0, ret = 1; for (auto e : g[v]) { if (e.to == p) continue; int r = dfs(e.to, v); ret += r; if (mx < r) mx = r, next[v] = e.to; } return ret; } void bfs(int r = 0) { int k = 0; queue q; q.emplace(r); while (!q.empty()) { auto h = q.front(); q.pop(); for (int v = h; v != -1; v = next[v]) { vid[v] = k++; head[v] = h; for (auto e : g[v]) { if (e.to == par[v] || e.to == next[v]) continue; q.emplace(e.to); } } } } vector build() { dfs(); bfs(); return vid; } void for_each(int v, int u, const function &f) { while (true) { if (vid[u] > vid[v]) swap(v, u); f(max(vid[head[v]], vid[u]), vid[v]); if (head[u] != head[v]) v = par[head[v]]; else break; } } }; int main() { int N, M, Q; cin >> N >> M >> Q; auto graph = UnWeightedGraph(N); for (int i = 0; i < M; i++) { int v, u; cin >> v >> u; v--, u--; graph.add_edge(v, u); graph.add_edge(u, v); } auto low = LowLink(graph); auto two = TwoEdgeConnectedComponent(graph); auto lll = low.build(); auto dict = two.decompose(lll.second); int V = *max_element(dict.begin(), dict.end()) + 1; auto hraph = UnWeightedGraph(V); for (int i = 0; i < N; i++) { for (auto e : graph[i]) { if (dict[i] == dict[e.to]) continue; hraph.add_edge(dict[i], dict[e.to]); } } auto hld = HeavyLightDecomposition(hraph); auto vid = hld.build(); auto seg = SegmentTree(V, [](int a, int b) { return max(a, b); }, -1); vector> q(V); unordered_map ma; for (int i = 0; i < Q; i++) { int n; cin >> n; if (n == 1) { int u, w; cin >> u >> w; u--; u = vid[dict[u]]; if (q[u].empty() || q[u].top() < w) { seg.update(u, w); } q[u].emplace(w); ma[w] = u; } else { int s, t; cin >> s >> t; s--, t--; int ans = -1; s = dict[s], t = dict[t]; hld.for_each(s, t, [&](int l, int r) { ans = max(ans, seg.query(l, r + 1)); }); cout << ans << '\n'; if (ans != -1) { int u = ma[ans]; q[u].pop(); seg.update(u, q[u].size() > 0 ? q[u].top() : -1); } } } return 0; }