#include using namespace std; vector > bridge; vector graph[100010]; pair edge[200010]; int pre[100010]; int low[100010]; int com[100010]; int n, m; int visited_cnt = 0; int dis_dfs(int idx, int from){ pre[idx] = visited_cnt; visited_cnt++; low[idx] = pre[idx]; for(int i = 0;i < graph[idx].size();i++){ int to = graph[idx][i]; if(pre[to] == -1){ low[idx] = min(low[idx], dis_dfs(to, idx)); }else{ if(from != to){ low[idx] = min(low[idx], low[to]); } } } return low[idx]; } vector subGraph[100010]; vector treeGraph[100010]; void make_dis_pair(int idx, int num){ com[idx] = num; for(int i = 0;i < subGraph[idx].size();i++){ if(com[subGraph[idx][i]] == -1){ make_dis_pair(subGraph[idx][i], num); } } return; } int disGraph(){ memset(pre, -1, sizeof(pre)); memset(low, -1, sizeof(low)); dis_dfs(0, -1); for(int i = 0;i < m;i++){ int fi = edge[i].first; int se = edge[i].second; if(pre[fi] < low[se] || pre[se] < low[fi]){ bridge.push_back(make_pair(min(fi, se), max(se, fi))); }else{ subGraph[fi].push_back(se); subGraph[se].push_back(fi); } } memset(com, -1, sizeof(com)); int pnum = 0; for(int i = 0;i < n;i++){ if(com[i] == -1){ make_dis_pair(i, pnum); pnum++; } } for(int i = 0;i < bridge.size();i++){ int fi = bridge[i].first; int se = bridge[i].second; treeGraph[com[fi]].push_back(com[se]); treeGraph[com[se]].push_back(com[fi]); } return pnum; } class SegmentTree{ public: int Size; pair Tree[1000000]; void init(int n){ Size = 1; while(Size < n) Size *= 2; for(int i = 0;i < Size;i++){ if(i < n){ Tree[Size-1+i] = make_pair(-1, i); }else{ Tree[Size-1+i] = make_pair(-2, 0); } } for(int i = Size-2;i >= 0;i--){ Tree[i] = max(Tree[i*2+1], Tree[i*2+2]); } return; } void update(int i, int num){ int idx = Size-1+i; Tree[idx] = make_pair(num, i); while(idx > 0){ idx = (idx-1)/2; Tree[idx] = max(Tree[idx*2+1], Tree[idx*2+2]); } } pair get_max(int a, int b, int l, int r, int k){ if(r <= a || b <= l) return make_pair(-1, 0); if(a <= l && r <= b) return Tree[k]; return max(get_max(a, b, l, (l+r)/2, 2*k+1), get_max(a, b, (l+r)/2, r, 2*k+2)); } pair getmax(int a, int b){ return get_max(a, b, 0, Size, 0); } }; #define swap(i,j) { int tmp = i; i = j; j = tmp; } vector tree[100010]; vector subtree[100010]; int par[100010] = {}; int num[100010] = {}; int vid[100010]; int nid[100010]; int head[100010]; int team[100010]; int size[100010] = {}; int b = 0; bool used[100010] = {}; SegmentTree segTree; void maketree(int i){ used[i] = true; for(int x = 0;x < treeGraph[i].size();x++){ if(!used[treeGraph[i][x]]){ par[treeGraph[i][x]] = i; tree[i].push_back(treeGraph[i][x]); maketree(treeGraph[i][x]); } } } int setnum(int i){ int ret = 1; for(int x = 0;x < tree[i].size();x++){ ret += setnum(tree[i][x]); } return num[i] = ret; } void dis(int n){ memset(team,-1,sizeof(team)); priority_queue > que; for(int i = 0;i < n;i++){ que.push(make_pair(num[i], i)); } int gnum = 0; int next; int pos = 0; int i; while(!que.empty()){ i = que.top().second; que.pop(); if(team[i] != -1) continue; team[i] = gnum; size[gnum]++; subtree[gnum].push_back(i); nid[i] = 0; int nn = 1; head[i] = i; vid[i] = pos; pos++; next = i; while(tree[next].size() != 0){ int maxi = 0; for(int j = 1;j < tree[next].size();j++){ if(num[tree[next][maxi]] < num[tree[next][j]]){ maxi = j; } } subtree[gnum].push_back(tree[next][maxi]); team[tree[next][maxi]] = gnum; head[tree[next][maxi]] = i; vid[tree[next][maxi]] = pos; nid[tree[next][maxi]] = nn; size[gnum]++; pos++; nn++; next = tree[next][maxi]; } gnum++; } return; } long long subDist[100010]; void build(int n){ maketree(0); setnum(0); dis(n); segTree.init(n); return; } pair getMax(int i, int j){ if(vid[i] > vid[j]) swap(i, j); if(head[i] == head[j]) return segTree.getmax(vid[i], vid[j]+1); return max(getMax(i, par[head[j]]), segTree.getmax(vid[head[j]], vid[j]+1)); } priority_queue que[100010]; int main(){ int q; cin >> n >> m >> q; for(int i = 0;i < m;i++){ cin >> edge[i].first >> edge[i].second; edge[i].first--, edge[i].second--; graph[edge[i].first].push_back(edge[i].second); graph[edge[i].second].push_back(edge[i].first); } int n2 = disGraph(); build(n2); int query, u, v; for(int p = 0;p < q;p++){ cin >> query >> u >> v; if(query == 1){ u--; que[vid[com[u]]].push(v); segTree.update(vid[com[u]], que[vid[com[u]]].top()); }else{ u--, v--; pair tmp; tmp = getMax(com[u], com[v]); cout << tmp.first << endl; if(tmp.first != -1){ que[tmp.second].pop(); if(que[tmp.second].size() == 0){ segTree.update(tmp.second, -1); }else{ segTree.update(tmp.second, que[tmp.second].top()); } } } } return 0; }