#include using namespace std; using ll = long long; #define int ll using VI = vector; using VVI = vector; using PII = pair; #define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i) #define REP(i, n) FOR(i, 0, n) #define ALL(x) x.begin(), x.end() #define PB push_back const ll INF = (1LL<<60); const int MOD = 1000000007; template T &chmin(T &a, const T &b) { return a = min(a, b); } template T &chmax(T &a, const T &b) { return a = max(a, b); } template bool IN(T a, T b, T x) { return a<=x&&x T ceil(T a, T b) { return a/b + !!(a%b); } template ostream &operator <<(ostream& out,const pair& a){ out<<'('< ostream &operator <<(ostream& out,const vector& a){ out<<'['; REP(i, a.size()) {out< st; par[rt] = -1; depth[rt] = 0; st.emplace(rt, 0); while(!st.empty()) { int v = st.top().first; int &i = st.top().second; if(i < (int)g[v].size()) { int u = g[v][i++]; if(u == par[v]) continue; par[u] = v; depth[u] = depth[v]+1; st.emplace(u,0); } else { st.pop(); int ma = 0; for(int u: g[v]){ if(u == par[v]) continue; sub[v] += sub[u]; if(ma < sub[u]) ma = sub[u], hvy[v] = u; } } } } // 根r、c番目の木についてchainについての情報をまとめる void bfs(int r, int c) { int &k = pos; queue que; que.push(r); while(que.size()) { int h = que.front(); que.pop(); for(int i=h; i!=-1; i=hvy[i]) { type[i] = c; vid[i] = k++; inv[vid[i]] = i; head[i] = h; for(int j: g[i]) { if(j!=par[i] && j!=hvy[i]) que.push(j); } } } } // 頂点に対する処理 [u,v] 開区間なので注意!!! void for_each(int u, int v, const function& f) { while(1){ if(vid[u]>vid[v]) swap(u,v); // [max(vid[head[v]],vid[u]), vid[v]] の区間についての操作を行う f(max(vid[head[v]], vid[u]), vid[v]); if(head[u]!=head[v]) v = par[head[v]]; else break; } } // 辺に対する処理 [u,v] 開区間なので注意!!! void for_each_edge(int u, int v, const function& f) { while(1) { if(vid[u]>vid[v]) swap(u,v); if(head[u]!=head[v]) { f(vid[head[v]], vid[v]); v = par[head[v]]; } else { if(u!=v) f(vid[u]+1, vid[v]); break; } } } // 頂点u, vのLCA int lca(int u,int v){ while(1) { if(vid[u]>vid[v]) swap(u,v); if(head[u]==head[v]) return u; v = par[head[v]]; } } // 頂点u, vの距離 int distance(int u, int v){ return depth[u] + depth[v] - 2*depth[lca(u,v)]; } }; struct twoEdgeComponents { int n; vector> g; // グラフの隣接リスト vector cmp; // 頂点iがどの連結成分に属するか vector> each_bcc; // i番目の連結成分の属する頂点 vector> bridge; // i番目の橋 vector order; vector inS; stack roots, S; twoEdgeComponents() {} twoEdgeComponents(int n_) : n(n_), g(VVI(n)) {} twoEdgeComponents(vector> g_) : n(g_.size()), g(g_) {} void add_edge(int p, int q) { g[p].push_back(q); g[q].push_back(p); } void dfs(int cur, int prev, int &k) { order[cur] = ++k; S.push(cur); inS[cur] = true; roots.push(cur); for(auto to: g[cur]) { if(order[to]==0) dfs(to, cur, k); else if(to!=prev && inS[to]) { while(order[roots.top()] > order[to]) roots.pop(); } } if(cur == roots.top()) { if(prev!=-1) bridge.push_back({prev, cur}); vector bcc; while(1) { int node = S.top(); S.pop(); inS[node] = false; bcc.push_back(node); if(node==cur) break; } each_bcc.push_back(bcc); roots.pop(); } } // 二重辺連結成分分解を行う void bcc() { order.assign(n, 0); inS.assign(n, false); cmp.assign(n, -1); int k = 0; for(int i=0; i> getbcc() { vector> h(each_bcc.size(), vector()); for(auto i: bridge) { int a = cmp[i.first], b = cmp[i.second]; h[a].push_back(b); h[b].push_back(a); } return h; } }; template class segmentTree { public: using M = monoid; using T = typename M::value_type; int sz; vector x; segmentTree(int n = 1e5) { sz = 1; while(sz < n) sz *= 2; init(); } void init() { x.assign(sz*2, M::id()); } // [a, b) T query(int a, int b, int k, int l, int r) { if(r <= a || b <= l) return M::id(); if(a <= l && r <= b) return x[k]; return M::f(query(a, b, 2*k+1, l, (l+r)/2), query(a, b, 2*k+2, (l+r)/2, r)); } T query(int a, int b) {return query(a, b, 0, 0, sz);} // 点更新 void update(int i, const T &val) { i += sz-1; x[i] = M::g(x[i], val); while(i > 0) { i = (i-1) / 2; x[i] = M::f(x[i*2+1], x[i*2+2]); } } }; template struct max_monoid { using value_type = T; static constexpr T id() { return std::numeric_limits::min(); } static T f(const T &a, const T &b) { return max(a, b); } static T g(const T &a, const T &b) { return b; } }; template using rmq = segmentTree>; signed main(void) { cin.tie(0); ios::sync_with_stdio(false); int n, m, q; cin >> n >> m >> q; VI a(m), b(m); VVI g(n); REP(i, m) { cin >> a[i] >> b[i]; a[i]--, b[i]--; g[a[i]].PB(b[i]); g[b[i]].PB(a[i]); } twoEdgeComponents bcc(g); bcc.bcc(); int sz = bcc.bridge.size()+1; HLDecomposition hld(sz); for(auto i: bcc.bridge) hld.add_edge(i.first, i.second); hld.build(); vector> que(sz); rmq seg(sz); map mp; REP(i, q) { int type; cin >> type; // 追加 if(type == 1) { int u, w; cin >> u >> w; u--; int ver = hld.vid[bcc.cmp[u]]; mp[w] = ver; if(que[ver].empty() || que[ver].top()> s >> t; s--, t--; s = bcc.cmp[s], t = bcc.cmp[t]; int ans = -1; hld.for_each(s, t, [&](int l, int r){ chmax(ans, seg.query(l, r+1)); }); cout << ans << endl; if(ans == -1) continue; int ver = mp[ans]; que[ver].pop(); int cost = que[ver].size()?que[ver].top():-1; seg.update(ver, cost); } } return 0; }