#include <bits/stdc++.h>
using namespace std;
int i, j, N, M, Que, deepest, MAX, X, Y, type;
int dist[300007], T[300007];
vector<int> L[300007];
bool sel[300007];
queue<pair<int, int> > Q;
void df(int start) {
  int node, level;
  vector<int>::iterator i;
  Q.push(make_pair(start, 0));
  sel[start] = true;
  MAX = 0;
  deepest = 0;
  while (!Q.empty()) {
    node = Q.front().first;
    level = Q.front().second;
    if (level >= MAX) {
      MAX = level;
      deepest = node;
    }
    for (i = L[node].begin(); i != L[node].end(); ++i) {
      if (sel[*i]) continue;
      sel[*i] = true;
      Q.push(make_pair(*i, level + 1));
    }
    Q.pop();
  }
}
void find_root(int node, int h, int pred = -1) {
  vector<int>::iterator i;
  MAX = ((h > MAX) ? h : MAX);
  T[node] = deepest;
  for (i = L[node].begin(); i != L[node].end(); ++i)
    if (*i != pred) find_root(*i, h + 1, node);
}
int multime(int X) {
  if (X == T[X]) return X;
  T[X] = multime(T[X]);
  return T[X];
}
void unite(int X, int Y) {
  X = multime(X);
  Y = multime(Y);
  dist[X] = ((dist[X] > (dist[X] + 1) / 2 + (dist[Y] + 1) / 2 + 1)
                 ? dist[X]
                 : (dist[X] + 1) / 2 + (dist[Y] + 1) / 2 + 1);
  dist[X] = ((dist[X] > dist[Y]) ? dist[X] : dist[Y]);
  T[Y] = X;
}
int main() {
  scanf("%d%d%d", &N, &M, &Que);
  while (M--) {
    scanf("%d%d", &X, &Y);
    L[X].push_back(Y);
    L[Y].push_back(X);
  }
  for (i = 1; i <= N; i++) {
    if (sel[i]) continue;
    df(i);
    MAX = 0;
    find_root(deepest, 0);
    dist[deepest] = MAX;
  }
  while (Que--) {
    scanf("%d", &type);
    if (type == 1) {
      scanf("%d", &X);
      printf("%d\n", dist[multime(X)]);
      continue;
    }
    scanf("%d%d", &X, &Y);
    if (multime(X) != multime(Y)) unite(X, Y);
  }
  return 0;
}
