#include #pragma GCD target ("arch=skylake-avx512") using namespace std; #define __ <<" "<< #define ___ <<" " #define bash push_back #define ALL(x) x.begin(),x.end() //#define int long long using Int = int; using ll = long long; using pii = pair; constexpr int INF = 0x3f3f3f3f; constexpr long long LINF = 0x3f3f3f3f3f3f3f3fLL; constexpr int SMOD = 1000000007; constexpr int NMOD = 998244353; constexpr int dx[]={1,0,-1,0,1,1,-1,-1}; constexpr int dy[]={0,-1,0,1,-1,1,-1,1}; inline bool inside(int x,int y,int w,int h){return (x>=0 && y>=0 && xbool chmax(T &a, const T&b){if(abool chmin(T &a, const T&b){if(bsub[G[v][0]]) swap(u,G[v][0]); } } void dfs_hld(int v,int c,int &pos) { vid[v]=pos++; inv[vid[v]]=v; type[v]=c; for(int u:G[v]){ if(u==par[v]) continue; head[u]=(u==G[v][0]?head[v]:u); dfs_hld(u,c,pos); } } public: vector< vector > G; vector vid, head, sub, par, dep, inv, type; HLD(int n): G(n),vid(n,-1),head(n),sub(n,1), par(n,-1),dep(n,0),inv(n),type(n){} // u <--> v void add_edge(int u,int v) { G[u].emplace_back(v); G[v].emplace_back(u); } void build(vector rs={0}) { int c=0,pos=0; for(int r:rs){ dfs_sz(r); head[r]=r; dfs_hld(r,c++,pos); } } 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]]; } } int distance(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } // for_each(vertex) // [l, r) <- attention!! // 頂点属性のクエリ用 template void for_each(int u, int v, const F& f) { while(1){ if(vid[u]>vid[v]) swap(u,v); f(max(vid[head[v]],vid[u]),vid[v]+1); if(head[u]!=head[v]) v=par[head[v]]; else break; } } template T for_each(int u,int v,T ti,const Q &q,const F &f){ T l=ti,r=ti; while(1){ if(vid[u]>vid[v]){ swap(u,v); swap(l,r); } l=f(l,q(max(vid[head[v]],vid[u]),vid[v]+1)); if(head[u]!=head[v]) v=par[head[v]]; else break; } return f(l,r); } // for_each(edge) // [l, r) <- attention!! template void for_each_edge(int u, int v,const F& f) { while(1){ if(vid[u]>vid[v]) swap(u,v); if(head[u]!=head[v]){ f(vid[head[v]],vid[v]+1); v=par[head[v]]; }else{ if(u!=v) f(vid[u]+1,vid[v]+1); break; } } } }; template< typename Monoid > struct SegmentTree { using F = function< Monoid(Monoid, Monoid) >; int sz; vector< Monoid > seg; const F f; const Monoid M1; SegmentTree(int n, const Monoid &M1, const F f) : f(f), M1(M1) { sz = 1; while(sz < n) sz <<= 1; seg.assign(2 * sz, M1); } void set(int k, const Monoid &x) { seg[k + sz] = x; } void build() { for(int k = sz - 1; k > 0; k--) { seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]); } } void update(int k, const Monoid &x) { k += sz; seg[k] = x; while(k >>= 1) { seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]); } } Monoid query(int a, int b) { Monoid L = M1, R = M1; for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) { if(a & 1) L = f(L, seg[a++]); if(b & 1) R = f(seg[--b], R); } return f(L, R); } Monoid operator[](const int &k) const { return seg[k + sz]; } }; struct LowLink{ int n,pos; vector ord,low,par,blg,num; vector > G,C,T; vector > > E; vector ap; vector > bs,cand; LowLink(int n):n(n),pos(0),ord(n,-1),low(n), par(n,-1),blg(n,-1),num(n,1),G(n){} // ord: DFS順のナンバリング // low: dfs木の葉方向の辺を0回以上, 後退辺を高々1回通って到達可能なordの最小値 // ある辺(u, v)が橋であるとき、ord[u] < low[v]を満たす // par: 根付き木の親 // blg[v]: 頂点vが属する成分の番号 // num[v]: 頂点vを根とする部分木のサイズ // G: 与えられる生のグラフ // C[id]: 成分idに属する頂点のリスト // blg と C は相互関係 // T[v]: 成分(v, T[v][i]) を結ぶ辺 // 分解後の木となる // E: DFS木の辺のリスト E[i][j]の(first, second)は辺だけど E[i]が何を表すかはわからん // ap: 関節点のリスト // bs: 橋のリスト 辺(first, second) は橋である // cand: もしかしたら適当利用なやつで考慮しなくてもいいかもしれない // public void add_edge(int u,int v){ G[u].emplace_back(v); G[v].emplace_back(u); } // bool is_bridge(int u,int v){ if(ord[u]>ord[v]) swap(u,v); return ord[u]=ord[v]){ E.emplace_back(); while(1){ auto e=cand.back(); cand.pop_back(); E.back().emplace_back(e); if(make_pair(min(u,v),max(u,v))==e) break; } } } } // ナンバリング void fill_component(int v){ C[blg[v]].emplace_back(v); for(int u:G[v]){ if(~blg[u]||is_bridge(u,v)) continue; blg[u]=blg[v]; fill_component(u); } } // 成分ごとにナンバリング void add_component(int v,int &k){ if(~blg[v]) return; blg[v]=k++; C.emplace_back(); fill_component(v); } // public int build(){ for(int i=0;i cnt(n,0); for(int i=0;i1) ap.emplace_back(i); //次数が1を超過 -> 関節点 sort(ap.begin(),ap.end()); ap.erase(unique(ap.begin(),ap.end()),ap.end()); int k=0; for(int i=0;i()); for(auto e:bs){ int u=blg[e.first],v=blg[e.second]; T[u].emplace_back(v); T[v].emplace_back(u); } return k; } }; bool visit[101010]; void dfs(vector>&e, int v, HLD&hld) { for(auto&&u:e[v]) { if(!visit[u]) { visit[u] = true; hld.add_edge(v, u); dfs(e, u, hld); } } } signed main() { int n, m, q; cin >> n >> m >> q; LowLink low(n); int a, b, c; for(int i = 0; i < m; i++) { cin >> a >> b; low.add_edge(a-1, b-1); } int after_n = low.build(); HLD hld(after_n); SegmentTree seg(after_n, pii(), [](pii a, pii b){return max(a, b);}); for(int i = 0; i < after_n; i++) { seg.set(i, pii(0, i + 1)); } visit[0] = true; dfs(low.T, 0, hld); hld.build(); vector> pque(after_n); for(int i = 0; i < q; i++) { cin >> a >> b >> c; if(a == 1) { b = hld.vid[low.blg[b-1]]; pque[b].push(c); seg.update(b, pii(pque[b].top(), b+1)); } else { b = low.blg[b-1]; c = low.blg[c-1]; pii maxv; hld.for_each(b, c, [&](int l, int r){chmax(maxv, seg.query(l, r));}); if(!maxv.first) { cout << -1 << endl; } else { cout << maxv.first << endl; int nex = 0; b = maxv.second ; pque[b-1].pop(); if(!pque[b-1].empty()) nex = pque[b-1].top(); seg.update(b - 1, pii(nex, b)); } } } return 0; }