#include #define rep(i,a,b) for(int i=a;i struct UnionFind { int par[NV], cnt[NV]; UnionFind() { rep(i, 0, NV) par[i] = i, cnt[i] = 1; } int operator[](int x) { return par[x] == x ? x : par[x] = operator[](par[x]); } void operator()(int x, int y) { x = operator[](x); y = operator[](y); if (x != y) par[x] = y, cnt[y] += cnt[x];}}; // xをyにくっつける struct SCC_BI { int NV = 0, time; vector > E; vector ord, llink, inin; stack roots, S; vector M, ART; vector > SC; vector > BR; void init(int NV) { this->NV = NV; E.clear(); E.resize(NV); } void add_edge(int x, int y) { assert(NV); E[x].push_back(y); E[y].push_back(x); } void dfs(int cur, int pre) { int art = 0, conn = 0, i, se = 0;ord[cur] = llink[cur] = ++time; S.push(cur); inin[cur] = 1; roots.push(cur);rep(i, 0, E[cur].size()) {int tar = E[cur][i]; if (ord[tar] == 0) {conn++; dfs(tar, cur);llink[cur] = min(llink[cur], llink[tar]); art += (pre != -1 && ord[cur] <= llink[tar]); if (ord[cur]ord[tar]) roots.pop();}else se++;} if (cur == roots.top()) {SC.push_back(vector());while (1) { i = S.top(); S.pop(); inin[i] = 0;SC.back().push_back(i);M[i] = SC.size() - 1; if (i == cur) break;}sort(SC.back().begin(), SC.back().end());roots.pop();} if (art || (pre == -1 && conn>1)) ART.push_back(cur);} void scc() { SC.clear(), BR.clear(), ART.clear(), M.resize(NV); ord.clear(), llink.clear(), inin.clear(); time = 0;ord.resize(NV); llink.resize(NV); inin.resize(NV); for (int i = 0; i> g; // vid : id -> vid head, heavy, parent : unknown // depth : id -> depth inv : vid -> id vector vid, head, heavy, parent, depth, inv; HLDecomposition(int n) : g(n), vid(n, -1), head(n), heavy(n, -1), parent(n), depth(n), inv(n) {} void add(int u, int v) { g[u].insert(v); g[v].insert(u); } void build(int root) { dfs(root, -1); bfs(); } int dfs(int curr, int prev) { parent[curr] = prev; int sub = 1, max_sub = 0; for (int next : g[curr]) if (next != prev) { depth[next] = depth[curr] + 1; int sub_next = dfs(next, curr); sub += sub_next; if (max_sub < sub_next) max_sub = sub_next, heavy[curr] = next; }return sub;} void bfs() { int k = 0; queue q({ 0 }); while (!q.empty()) { int h = q.front(); q.pop(); for (int i = h; i != -1; i = heavy[i]) {vid[i] = k++; inv[vid[i]] = i; head[i] = h; for (int j : g[i]) if (j != parent[i] && j != heavy[i]) q.push(j);}}} void foreach(int u, int v, function f) { if (vid[u] > vid[v]) swap(u, v); f(max(vid[head[v]], vid[u]), vid[v]); if (head[u] != head[v]) foreach(u, parent[head[v]], f);} int ancestor(int u, int d) { while (true) { if (depth[head[u]] > depth[u] - d) { d -= depth[u] - depth[head[u]] + 1; if (head[u] == 0) return 0; u = parent[head[u]];} else return inv[vid[u] - d];} } // uのd個上の頂点を返す(無いなら0) int lca(int u, int v) { if (vid[u] > vid[v]) swap(u, v); if (head[u] == head[v]) return u; return lca(u, parent[head[v]]); } int distance(int u, int v) { return depth[u] + depth[v] - 2 * depth[lca(u, v)]; }}; #define def make_pair(-1, -1) template struct SegTree { V comp(V l, V r) { return max(l,r); }; vector val; SegTree() { val = vector(NV * 2, def); } V get(int l, int r) { //[l,r] if (l > r) return def; l += NV; r += NV + 1; V ret = def; while (l < r) { if (l & 1) ret = comp(ret, val[l++]); if (r & 1) ret = comp(ret, val[--r]); l /= 2; r /= 2; } return ret; } void update(int i, V v) { i += NV; val[i] = v; while (i>1) i >>= 1, val[i] = comp(val[i * 2], val[i * 2 + 1]); } void add(int i, V v) { update(i, val[i + NV] + v); } }; /*---------------------------------------------------------------------------------------------------             ∧_∧       ∧_∧  (´<_` )  Welcome to My Coding Space!      ( ´_ゝ`) /  ⌒i     /   \    | |     /   / ̄ ̄ ̄ ̄/  |   __(__ニつ/  _/ .| .|____      \/____/ (u ⊃ ---------------------------------------------------------------------------------------------------*/ int N, M, Q; vector E[101010]; SCC_BI scc; UnionFind<101010> uf; SegTree, 101010> st; priority_queue que[101010]; //--------------------------------------------------------------------------------------------------- int ans_i = -1; void _main() { cin >> N >> M >> Q; scc.init(N); rep(i, 0, M) { int a, b; cin >> a >> b; a--; b--; E[a].push_back(b); E[b].push_back(a); scc.add_edge(a, b); } scc.scc(); for (auto p : scc.SC) rep(i, 1, p.size()) uf(p[0], p[i]); /*for (auto p : scc.SC) { printf("<%d> ", uf[p[0]]); rep(i, 0, p.size()) printf("%d ", p[i]); printf("\n"); }*/ HLDecomposition hld(N); rep(i, 0, N) for (int j : E[i]) { int a = uf[i]; int b = uf[j]; if (a != b) hld.add(a, b); } hld.build(uf[0]); rep(i, 0, N) st.update(i, { -1, -1 }); rep(q, 0, Q) { int a, b, c; cin >> a >> b >> c; if (a == 1) { b = hld.vid[uf[b - 1]]; if (que[b].empty() || que[b].top() < c) { que[b].push(c); st.update(b, { c, b }); } } else { b = uf[b - 1]; c = uf[c - 1]; ans_i = -1; hld.foreach(b, c, [](int x, int y) { //printf("] %d %d ]\n", x, y); auto p = st.get(x, y); if (ans_i < 0) ans_i = p.second; else if (st.get(ans_i, ans_i) < p) ans_i = p.second; }); if (ans_i < 0) { printf("-1\n"); } else { auto p = st.get(ans_i, ans_i); printf("%d\n", p.first); que[ans_i].pop(); if (que[ans_i].empty()) st.update(ans_i, { -1, -1 }); else st.update(ans_i, { que[ans_i].top(), ans_i }); } } } }