#include <bits/stdc++.h>
using namespace std;
template <class T>
T max(T a, T b, T c) {
  return max(a, max(b, c));
}
int nextInt() {
  int x = 0, p = 1;
  char c;
  do {
    c = getchar();
  } while (c <= 32);
  if (c == '-') {
    p = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  return x * p;
}
const int maxn = 300500;
int n, m, q;
vector<int> g[maxn];
bool used[maxn];
int p[maxn], sz[maxn], diameter[maxn];
int maxi, maxiV;
void dfs(int v, int depth, int p) {
  if (depth > maxi) {
    maxi = depth;
    maxiV = v;
  }
  for (size_t i = 0; i < g[v].size(); i++) {
    int to = g[v][i];
    if (to != p) dfs(to, depth + 1, v);
  }
}
int findLongestWay(int v) {
  maxi = -1;
  dfs(v, 0, -1);
  maxi = -1;
  dfs(maxiV, 0, -1);
  return maxi;
}
void init() {
  for (int i = 1; i <= n; i++) p[i] = i, sz[i] = 1, diameter[i] = 0;
}
int getSet(int v) {
  if (p[v] == v) return v;
  return p[v] = getSet(p[v]);
}
void unionSets1(int x, int y) {
  x = getSet(x);
  y = getSet(y);
  if (sz[x] > sz[y]) swap(x, y);
  sz[y] += sz[x];
  p[x] = y;
}
int rad(int x) { return (diameter[x] + 1) / 2; }
void unionSets2(int x, int y) {
  x = getSet(x);
  y = getSet(y);
  if (x == y) return;
  if (sz[x] > sz[y]) swap(x, y);
  sz[y] += sz[x];
  p[x] = y;
  diameter[y] = max(rad(x) + rad(y) + 1, diameter[x], diameter[y]);
}
int query(int x) { return diameter[getSet(x)]; }
int main() {
  n = nextInt();
  m = nextInt();
  q = nextInt();
  init();
  for (int i = 1; i <= m; i++) {
    int x, y;
    x = nextInt();
    y = nextInt();
    g[x].push_back(y);
    g[y].push_back(x);
    unionSets1(x, y);
  }
  for (int i = 1; i <= n; i++) {
    int pp = getSet(i);
    if (!used[pp]) {
      used[pp] = 1;
      diameter[pp] = findLongestWay(i);
    }
  }
  while (q--) {
    int t, x, y;
    t = nextInt();
    if (t == 2) {
      x = nextInt();
      y = nextInt();
      unionSets2(x, y);
    } else {
      x = nextInt();
      printf("%d\n", query(x));
    }
  }
}
