import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.NoSuchElementException; import java.util.PriorityQueue; class Main implements Runnable { public static void main(String[] args) { new Main().run(); } class State { int i; int parent; int j;// 操作後g[i][j]に潜る public State(int i_, int parent_, int j_) { i = i_; parent = parent_; j = j_; } } int order = 0; int cols = 0; ArrayDeque pnd = new ArrayDeque(); void dfs(ArrayList[] g, int cur, int par, int[] ord, int[] low, int[] col, boolean[] marked) { ord[cur] = order; low[cur] = order; ++order; pnd.addFirst(cur); for (int dst : g[cur]) { if (dst == par || marked[dst]) continue; if (ord[dst] == -1) dfs(g, dst, cur, ord, low, col, marked); low[cur] = Math.min(low[cur], low[dst]); } if (low[cur] == ord[cur]) { while (true) { int v = pnd.pollFirst(); col[v] = cols; marked[v] = true; if (v == cur) break; } ++cols; } } int two_edge_connected_componets(ArrayList[] g, int[] col) { int n = g.length; Arrays.fill(col, -1); int[] low = new int[n]; int[] ord = new int[n]; boolean[] marked = new boolean[n]; Arrays.fill(low, -1); Arrays.fill(ord, -1); for (int ii = 0; ii < n; ++ii) { if (ord[ii] == -1) { dfs(g, ii, -1, ord, low, col, marked); } } return cols; } @SuppressWarnings("unchecked") public void run() { Scanner sc = new Scanner(); PrintWriter pw = new PrintWriter(System.out); int n = sc.nextInt(); int m = sc.nextInt(); int q = sc.nextInt(); ArrayList[] g = new ArrayList[n]; for (int i = 0; i < n; ++i) { g[i] = new ArrayList<>(); } for (int i = 0; i < m; ++i) { int a = sc.nextInt() - 1; int b = sc.nextInt() - 1; g[a].add(b); g[b].add(a); } int[] col = new int[n]; int cols = two_edge_connected_componets(g, col); ArrayList[] h = new ArrayList[cols]; PriorityQueue[] w = new PriorityQueue[cols]; for (int i = 0; i < cols; ++i) { w[i] = new PriorityQueue<>(new Comparator() { @Override public int compare(Long o1, Long o2) { return -Long.compare(o1, o2); } }); } for (int i = 0; i < cols; ++i) { w[i].add(-1L); } for (int i = 0; i < cols; ++i) { h[i] = new ArrayList<>(); } for (int i = 0; i < n; ++i) { for (int j : g[i]) { int a = col[i]; int b = col[j]; if (a == b) continue; if (h[a].contains(b)) continue; h[a].add(b); h[b].add(a); } } for (int i = 0; i < cols; ++i) { Collections.sort(h[i]); for (int j = 0; j < h[i].size(); ++j) { while (j + 1 < h[i].size() && h[i].get(j) == h[i].get(j + 1)) { h[i].remove(j + 1); } } } HLDecomposition hl = new HLDecomposition(cols); for (int i = 0; i < cols; ++i) { for (int j : h[i]) { if (i > j) { hl.ae(i, j); } } } hl.pre(); SegmentTree st = new SegmentTree(cols); int[] ref = new int[cols]; Arrays.fill(ref, -1); for (int i = 0; i < cols; ++i) { ref[hl.id[i]] = i; } while (q-- > 0) { int t = sc.nextInt(); if (t == 1) {// modification query int u = sc.nextInt() - 1; long v = sc.nextInt(); u = col[u]; w[u].add(v); st.setVal(hl.id[u], w[u].peek()); } else {// ouput query int src = sc.nextInt() - 1; int dst = sc.nextInt() - 1; src = col[src]; dst = col[dst]; long v = output(src, dst, hl, st); pw.println(v == -1 ? v : v >> 32); if (v != -1) { w[ref[(int) v]].poll(); st.setVal((int) v, w[ref[(int) v]].peek()); } } } pw.close(); } long output(int a, int b, HLDecomposition hl, SegmentTree st) { long ea = -1; long eb = -1; while (hl.head[a] != hl.head[b]) { if (hl.depth[hl.head[a]] < hl.depth[hl.head[b]]) { int tmp = a; a = b; b = tmp; long tmp_e = ea; ea = eb; eb = tmp_e; } ea = merge(st.query(hl.id[hl.head[a]], hl.id[a] + 1), ea); a = hl.parent[hl.head[a]]; } if (hl.depth[a] < hl.depth[b]) { int tmp = a; a = b; b = tmp; long tmp_e = ea; ea = eb; eb = tmp_e; } return merge(eb, merge(st.query(hl.id[b], hl.id[a] + 1), ea)); } long merge(long a, long b) { return Math.max(a, b); } class SegmentTree { int n; long[] Vs; public SegmentTree(int n_) { n = 1; while (n < n_) { n *= 2; } Vs = new long[2 * n - 1]; for (int i = 0; i < n; ++i) { Vs[i + n - 1] = -1; } for (int i = n - 2; i >= 0; --i) { Vs[i] = merge(Vs[2 * i + 1], Vs[2 * i + 2]); } } void setVal(int k, long val) { k += n - 1; if (val != -1) Vs[k] = val << 32 | (k - (n - 1)); else Vs[k] = -1; while (k > 0) { k = (k - 1) / 2; Vs[k] = merge(Vs[2 * k + 1], Vs[2 * k + 2]); } } // [a,b),[l,r) long query(int a, int b) { return query(a, b, 0, n, 0); } long query(int a, int b, int l, int r, int k) { if (b <= l || r <= a) { return -1L; } if (a <= l && r <= b) { return Vs[k]; } else { long vl = query(a, b, l, (l + r) / 2, 2 * k + 1); long vr = query(a, b, (l + r) / 2, r, 2 * k + 2); return merge(vl, vr); } } } class HLDecomposition { int n; int[] depth; int[] head; int[] heavy; int[] parent; int[] sz; ArrayList[] g; int[] id; @SuppressWarnings("unchecked") public HLDecomposition(int n) { this.n = n; depth = new int[n]; head = new int[n]; heavy = new int[n]; parent = new int[n]; id = new int[n]; sz = new int[n]; g = new ArrayList[n]; for (int i = 0; i < n; ++i) { g[i] = new ArrayList<>(); } Arrays.fill(head, -1); Arrays.fill(id, -1); Arrays.fill(parent, -1); } void ae(int a, int b) { g[a].add(b); g[b].add(a); } void pre() { dfs(0, -1); bfs(); } void bfs() { ArrayDeque pend = new ArrayDeque<>(); int gen = 0; pend.add(0); while (!pend.isEmpty()) { int v = pend.pollFirst(); int top = v; for (; v != -1; v = heavy[v]) { id[v] = gen++; head[v] = top; for (int d : g[v]) { if (d == parent[v] || d == heavy[v]) { continue; } pend.add(d); } } } } int lca(int u, int v) { if (head[u] != head[v]) { if (depth[head[u]] < depth[head[v]]) { int tmp = u; u = v; v = tmp; } return lca(parent[head[u]], v); } else { if (depth[u] > depth[v]) { int tmp = u; u = v; v = tmp; } return u; } } int dfs(int c, int p) { parent[c] = p; int s = 1; int to = -1; for (int d : g[c]) { if (d == p) continue; depth[d] = depth[c] + 1; s += dfs(d, c); if (to == -1 || sz[d] > sz[to]) { to = d; } } sz[c] = s; heavy[c] = to; return s; } } class Scanner { private final InputStream in = System.in; private final byte[] buffer = new byte[1024]; private int ptr = 0; private int buflen = 0; private boolean hasNextByte() { if (ptr < buflen) { return true; } else { ptr = 0; try { buflen = in.read(buffer); } catch (IOException e) { e.printStackTrace(); } if (buflen <= 0) { return false; } } return true; } public int nextInt() { return (int) nextLong(); } private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1; } private boolean isPrintableChar(int c) { return 33 <= c && c <= 126; } private void skipUnprintable() { while (hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; } public boolean hasNext() { skipUnprintable(); return hasNextByte(); } public String next() { if (!hasNext()) throw new NoSuchElementException(); StringBuilder sb = new StringBuilder(); int b = readByte(); while (isPrintableChar(b)) { sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } public long nextLong() { if (!hasNext()) throw new NoSuchElementException(); long n = 0; boolean minus = false; int b = readByte(); if (b == '-') { minus = true; b = readByte(); } if (b < '0' || '9' < b) { throw new NumberFormatException(); } while (true) { if ('0' <= b && b <= '9') { n *= 10; n += b - '0'; } else if (b == -1 || !isPrintableChar(b)) { return minus ? -n : n; } else { throw new NumberFormatException(); } b = readByte(); } } } static void tr(Object... objects) { System.out.println(Arrays.deepToString(objects)); } }