#include<bits/stdc++.h>

#define x first

#define y second

#define pb push_back

#define inf 0x3f3f3f3f

#define mod 1000000007

#define sq(_) ((_)*(_))

#define bit(x, y) (((x)>>(y))&1)

#define bctz(x) (__builtin_ctz(x))

#define bclz(x) (__builtin_clz(x))

#define bclzl(x) (__builtin_clzl(x))

#define bctzl(x) (__builtin_ctzl(x))

#define bpt(x) (__builtin_popcount(x))

#define bptl(x) (__builtin_popcountll(x))

#define PQ priority_queue<pii, vector<pii>, greater<pii> >

using namespace std;

typedef double DO;

typedef long long INT;

typedef pair<int, int> pii;

typedef pair<pii, int> pi3;

typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, const U &b) {if(a>b) a=b;}

template<typename T, typename U> inline void smax(T &a, const U &b) {if(a<b) a=b;}

template <class T> inline void gn(T &x) {char c, sg=0; while(c=getchar(), (c>'9' || c<'0') && c!='-'); for((c=='-' ? sg=1, c=getchar() : 0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0'; if(sg) x=-x;}

template <class T1, class T2> inline void gn(T1 &x1, T2 &x2) {gn(x1), gn(x2);}

template <class T1, class T2, class T3> inline void gn(T1 &x1, T2 &x2, T3 &x3) {gn(x1, x2), gn(x3);}

template <class T1, class T2, class T3, class T4> inline void gn(T1 &x1, T2 &x2, T3 &x3, T4 &x4) {gn(x1, x2, x3), gn(x4);}

template <class T1, class T2, class T3, class T4, class T5> inline void gn(T1 &x1, T2 &x2, T3 &x3, T4 &x4, T5 &x5) {gn(x1, x2, x3, x4), gn(x5);}

template <class T> inline void print(T x) {if(x<0) {putchar('-'); return print(-x);} if(x<10) {putchar('0'+x); return ;} print(x/10); putchar(x%10+'0');}

template <class T> inline void println(T x) {print(x); putchar('\n');}

template <class T> inline void printsp(T x) {print(x); putchar(' ');}

template <class T1, class T2> inline void print(T1 x1, T2 x2) {printsp(x1), println(x2);}

template <class T1, class T2, class T3> inline void print(T1 x1, T2 x2, T3 x3) {printsp(x1), printsp(x2), println(x3);}

template <class T1, class T2, class T3, class T4> inline void print(T1 x1, T2 x2, T3 x3, T4 x4) {printsp(x1), printsp(x2), printsp(x3), println(x4);}

template <class T1, class T2, class T3, class T4, class T5> inline void print(T1 x1, T2 x2, T3 x3, T4 x4, T5 x5) {printsp(x1), printsp(x2), printsp(x3), printsp(x4), println(x5);}

int power(int a, int b, int m, int ans=1) {

	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;

	return ans;

}

#define NN 300010

VI adj[NN];

int vst[NN], root[NN];

int d[NN], mx[NN];

void dfs(int u, int fa) {

	vst[u]=1;

	root[u]=fa;

	int one=0, two=0;

	for(int i=adj[u].size(); i--; ) {

		int v=adj[u][i];

		if(!vst[v]) {

			dfs(v, u);

			if(mx[v]+1>one) {

				two=one;

				one=mx[v]+1;

			}

			else if(mx[v]+1>two) two=mx[v]+1;

		}

	}

	smax(d[u], one+two);

	mx[u]=one;

}

int find_root(int u) {

	if(u==root[u]) return u;

	return root[u]=find_root(root[u]);

}

int main() {

#ifndef	ONLINE_JUDGE

	freopen("in.in", "r", stdin);

	freopen("out.out", "w", stdout);

#endif

	int n, m, q;

	gn(n, m, q);

	while(m--) {

		int u, v;

		gn(u, v);

		adj[u].pb(v);

		adj[v].pb(u);

	}

	for(int i=1; i<=n; i++) if(!vst[i]) {

		root[i]=i;

		dfs(i, i);

	}

	while(q--) {

		int t, x, y;

		gn(t, x);

		if(t==1) println(d[find_root(x)]);

		else {

			gn(y);

			x=find_root(x), y=find_root(y);

			if(x!=y) {

				root[x]=y;

				d[y]=max(max(d[x], d[y]), (d[x]+1>>1)+(d[y]+1>>1)+1);

			}

		}

	}

}


#include <bits/stdc++.h>

#define inf 0x3f3f3f3f

#define MOD 1000000007

#define pb push_back

#define sq(x) ((x)*(x))

#define x first

#define y second

#define eps 1e-9

#define bpt(x) (__builtin_popcount(x))

#define bptl(x) (__builtin_popcountll(x))

#define bit(x, y) (((x)>>(y))&1)

#define bclz(x) (__builtin_clz(x))

#define bclzl(x) (__builtin_clzll(x))

#define bctz(x) (__builtin_ctz(x))

#define bctzl(x) (__builtin_ctzll(x))

#define sgn(x) (((x)>eps)-((x)<-eps))

#define PQ priority_queue<pii, vector<pii>, greater<pii> >

using namespace std;

typedef long long INT;

typedef vector<int> VI;

typedef pair<int, int> pii;

typedef pair<pii, int> pi3;

typedef double DO;

template<typename T, typename U> inline void smin(T &a, U b) {if (a>b) a=b;}

template<typename T, typename U> inline void smax(T &a, U b) {if (a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}

template<class T, class T1>inline void gn(T &x, T1 &y) {gn(x); gn(y);}

template<class T, class T1, class T2>inline void gn(T &x, T1 &y, T2 &z) {gn(x); gn(y); gn(z);}

template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}

template<class T>inline void printsp(T x) {print(x); putchar(' ');}

template<class T>inline void println(T x) {print(x); putchar('\n');}

template<class T, class U>inline void print(T x, U y) {printsp(x); println(y);}

template<class T, class U, class V>inline void print(T x, U y, V z) {printsp(x); printsp(y); println(z);}

int power(int a, int b, int m, int ans=1) {

	for (; b; b>>=1, a=1LL*a*a%m) if (b&1) ans=1LL*ans*a%m;

	return ans;

}

#define NN 101010

int vst[NN], flag, d[NN], root[NN];

int find(int u) {

	if (u==root[u]) return u;

	return root[u]=find(root[u]);

}

VI adj[NN];

pii dfs(int u, int id) {

	pii a=pii(-1, u);

	vst[u]=flag; root[u]=id;

	for (int i=0; i<adj[u].size(); i++) {

		int v=adj[u][i];

		if (vst[v]==flag) continue;

		pii b=dfs(v, id);

		smax(a, b);

	}

	a.x++;

	return a;

}

int main() {

#ifndef ONLINE_JUDGE

	freopen("in.in", "r", stdin);

	freopen("out.out", "w", stdout);

#endif

	int n, m, q, u, v;

	gn(n, m, q);

	for (int i=0; i<m; i++) {

		gn(u, v);

		adj[u].pb(v); adj[v].pb(u);

	}

	for (int i=1; i<=n; i++) if (!vst[i]) {

		++flag;

		pii a=dfs(i, i);

		d[i]=dfs(a.y, i).x;

	}

	int t;

	while (q--) {

		gn(t);

		if (t==1) {

			gn(u);

			println(d[find(u)]);

		} else {

			gn(u, v);

			u=find(u); v=find(v);

			if (u==v) continue;

			d[u]=max(max(d[u], d[v]), (d[u]+1>>1)+(d[v]+1>>1)+1);

			root[v]=u;

		}

	}

	return 0;

}


#include <bits/stdc++.h>

#define inf 0x3f3f3f3f

#define MOD 1000000007

#define pb push_back

#define sq(x) ((x)*(x))

#define x first

#define y second

#define eps 1e-9

#define bpt(x) (__builtin_popcount(x))

#define bptl(x) (__builtin_popcountll(x))

#define bit(x, y) (((x)>>(y))&1)

#define bclz(x) (__builtin_clz(x))

#define bclzl(x) (__builtin_clzll(x))

#define bctz(x) (__builtin_ctz(x))

#define bctzl(x) (__builtin_ctzll(x))

#define sgn(x) (((x)>eps)-((x)<-eps))

#define PQ priority_queue<pii, vector<pii>, greater<pii> >

using namespace std;

typedef long long INT;

typedef vector<int> VI;

typedef pair<int, int> pii;

typedef pair<pii, int> pi3;

typedef double DO;

template<typename T, typename U> inline void smin(T &a, U b) {if (a>b) a=b;}

template<typename T, typename U> inline void smax(T &a, U b) {if (a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}

template<class T, class T1>inline void gn(T &x, T1 &y) {gn(x); gn(y);}

template<class T, class T1, class T2>inline void gn(T &x, T1 &y, T2 &z) {gn(x); gn(y); gn(z);}

template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}

template<class T>inline void printsp(T x) {print(x); putchar(' ');}

template<class T>inline void println(T x) {print(x); putchar('\n');}

template<class T, class U>inline void print(T x, U y) {printsp(x); println(y);}

template<class T, class U, class V>inline void print(T x, U y, V z) {printsp(x); printsp(y); println(z);}

int power(int a, int b, int m, int ans=1) {

	for (; b; b>>=1, a=1LL*a*a%m) if (b&1) ans=1LL*ans*a%m;

	return ans;

}

const int C=333333;

VI adj[C];

int root[C],sz[C],d[C],src;

pii f;

int find_root(int u){

	return (root[u] == u ? u : root[u] = find_root(root[u]));

}

void add(int u,int v){

	int uu=find_root(u),vv=find_root(v);

	if(uu==vv) return;

	sz[vv]+=sz[uu];

	root[uu]=vv;

	smax(d[vv],max(d[uu],(1+d[uu])/2+(1+d[vv])/2+1));

}

void dfs(int u,int dp=0){

	root[u]=src; sz[src]++;

	if(dp>f.y){

		f.y=dp; f.x=u;

	}

	for(int i=0; i<adj[u].size(); i++){

		int v=adj[u][i];

		if(root[v]) continue;

		dfs(v,dp+1);

	}

}

void rdfs(int u,int dp=0,int fa=0){

	smax(d[src],dp);

	for(int i=0; i<adj[u].size(); i++){

		int v=adj[u][i];

		if(v==fa) continue;

		rdfs(v,dp+1,u);

	}

}

void solve_C(){

	int n,m,q,u,v;

	gn(n,m,q);

	for(int i=0; i<m; i++){

		gn(u,v);

		adj[u].pb(v);adj[v].pb(u);

	}

	for(int i=1; i<=n; i++) if(!root[i]){

		f.x=i; f.y=0; src=i;

		dfs(i);

		rdfs(f.x);

	}

	while(q--){

		int t;gn(t);

		if(t==1){

			gn(u);

			u=find_root(u);

			println(d[u]);

		}

		else{

			gn(u,v);

			add(u,v);

		}

	}

	exit(0);

}

int main() {

#ifndef ONLINE_JUDGE

	freopen("in.in", "r", stdin);

	freopen("out.out", "w", stdout);

#endif

	solve_C();

	return 0;

}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int bfs_id(int x)
{
	memset(dis,-1,sizeof(dis));
	int q[300005],Front,End;
	memset(q,0,sizeof(q));
	Front=1;
	End=2;
	q[Front]=x;
	dis[x]=0;
	int res=x,Max=0;
	while (Front<End)
	{
		x=q[Front];
		Front++;
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q[End++]=tx;
				if (dis[tx]>Max)
				{
					Max=dis[tx];
					res=tx;
				}
			}
		}
	}
	return res;
}

int bfs_dis(int x)
{
	memset(dis,-1,sizeof(dis));
	int q[300005],Front,End;
	memset(q,0,sizeof(q));
	Front=1;
	End=2;
	q[Front]=x;
	dis[x]=0;
	int Max=0;
	while (Front<End)
	{
		x=q[Front];
		Front++;
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q[End++]=tx;
				Max=max(Max,dis[tx]);
			}
		}
	}
	return Max;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	memset(diam,0,sizeof(diam));
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=bfs_id(root);
			diam[root]=bfs_dis(id);
//			cout<<root<<" "<<id<<" "<<diam[root]<<endl;
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		cin>>type;
		if (type==1)
		{
			cin>>x;
			cout<<diam[fnd(x)]<<endl;
		}
		else
		{
			cin>>x>>y;
			uion(x,y);
		}
	}
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int bfs_id(int x)
{
	memset(dis,-1,sizeof(dis));
	int q[300005],Front,End;
	memset(q,0,sizeof(q));
	Front=1;
	End=2;
	q[Front]=x;
	dis[x]=0;
	int res=x,Max=0;
	while (Front<End)
	{
		x=q[Front];
		Front++;
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q[End++]=tx;
				if (dis[tx]>Max)
				{
					Max=dis[tx];
					res=tx;
				}
			}
		}
	}
	return res;
}

int bfs_dis(int x)
{
	memset(dis,-1,sizeof(dis));
	int q[300005],Front,End;
	memset(q,0,sizeof(q));
	Front=1;
	End=2;
	q[Front]=x;
	dis[x]=0;
	int Max=0;
	while (Front<End)
	{
		x=q[Front];
		Front++;
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q[Front++]=tx;
				Max=max(Max,dis[tx]);
			}
		}
	}
	return Max;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	memset(diam,0,sizeof(diam));
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=bfs_id(root);
			diam[root]=bfs_dis(id);
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		cin>>type;
		if (type==1)
		{
			cin>>x;
			cout<<diam[fnd(x)]<<endl;
		}
		else
		{
			cin>>x>>y;
			uion(x,y);
		}
	}
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int dfs(int par,int x)
{
	int res=x;
	for (int i=0;i<v[x].size();i++)
	{
		int tx=v[x][i];
		if (par!=tx)
		{
			dis[tx]=dis[x]+1;
			int tmp=dfs(x,tx);
			if (dis[tmp]>dis[res]) res=tmp;
		}
	}
	return res;
}

int main()
{
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	memset(diam,0,sizeof(diam));
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=dfs(0,root);
			dis[id]=0;
			diam[root]=dis[dfs(0,id)];
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		scanf("%d",&type);
		if (type==1)
		{
			scanf("%d",&x);
			printf("%d\n",diam[fnd(x)]);
		}
		else
		{
			scanf("%d%d",&x,&y);
			uion(x,y);
		}
	}
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int bfs_id(int x)
{
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(x);
	dis[x]=0;
	int res=x,Max=0;
	while (!q.empty())
	{
		x=q.front();
		q.pop();
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q.push(tx);
				if (dis[tx]>Max)
				{
					Max=dis[tx];
					res=tx;
				}
			}
		}
	}
	return res;
}

int bfs_dis(int x)
{
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(x);
	dis[x]=0;
	int Max=0;
	while (!q.empty())
	{
		x=q.front();
		q.pop();
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q.push(tx);
				if (dis[tx]>Max)
				{
					Max=dis[tx];
				}
			}
		}
	}
	return Max;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	memset(diam,0,sizeof(diam));
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=bfs_id(root);
			diam[root]=bfs_dis(id);
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		cin>>type;
		if (type==1)
		{
			cin>>x;
			cout<<diam[fnd(x)]<<endl;
		}
		else
		{
			cin>>x>>y;
			uion(x,y);
		}
	}
	return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <set>
#include <algorithm>
#include <map>
#include <queue>
#include <cmath>
#include <ctime>
#include <list>
#include <sstream>
#include <string>
#include <cstring>
#include <utility>
using namespace std;
int n,m,q,parent[300010],diam[300010],deep[300010],xx,yy,state;
vector <int> v[300010];

int fnd(int x)
{
	return (x==parent[x]?x:parent[x]=fnd(parent[x]));
}

inline void uion1(int x,int y)
{
	int rotx=fnd(x);
	int roty=fnd(y);
	if (rotx!=roty)
	{
		parent[roty]=rotx;
	}
}

inline void uion2(int x,int y)
{
	int rotx=fnd(x);
	int roty=fnd(y);
	parent[roty]=rotx;
	diam[rotx]=max(max(diam[rotx],diam[roty]),((diam[rotx]+1)/2+(diam[roty]+1)/2+1));
}

int dfs(int father,int x)
{
	int ans=x;
	for (int i=0;i<v[x].size();i++)
	{
		if (v[x][i]!=father)
		{
			deep[v[x][i]]=deep[x]+1;
			int nxt=dfs(x,v[x][i]);
			if (deep[nxt]>deep[ans]) ans=nxt;
		}
	}
	return ans;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		parent[i]=i;
	for (int i=1;i<=m;i++)
	{
		cin>>xx>>yy;
		uion1(xx,yy);
		v[xx].push_back(yy);
		v[yy].push_back(xx);
	}
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (diam[root]==0)
		{
			xx=dfs(0,i);
			deep[xx]=0;
			yy=dfs(0,xx);
			diam[root]=deep[yy];
		}
	}
	for (int i=1;i<=q;i++)
	{
		cin>>state;
		if (state==1)
		{
			cin>>xx;
			cout<<diam[fnd(xx)]<<endl;
		}
		else
		{
			cin>>xx>>yy;
			uion2(xx,yy);
		}
	}
	return 0;
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int bfs_id(int x)
{
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(x);
	dis[x]=0;
	int res=x,Max=0;
	while (!q.empty())
	{
		x=q.front();
		q.pop();
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q.push(tx);
				if (dis[tx]>Max)
				{
					Max=dis[tx];
					res=tx;
				}
			}
		}
	}
	return res;
}

int bfs_dis(int x)
{
	memset(dis,-1,sizeof(dis));
	queue<int> q;
	q.push(x);
	dis[x]=0;
	int Max=0;
	while (!q.empty())
	{
		x=q.front();
		q.pop();
		for (int i=0;i<v[x].size();i++)
		{
			int tx=v[x][i];
			if (dis[tx]==-1)
			{
				dis[tx]=dis[x]+1;
				q.push(tx);
				if (dis[tx]>Max)
				{
					Max=dis[tx];
				}
			}
		}
	}
	return Max;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=bfs_id(root);
			diam[root]=bfs_dis(id);
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		cin>>type;
		if (type==1)
		{
			cin>>x;
			cout<<diam[fnd(x)]<<endl;
		}
		else
		{
			cin>>x>>y;
			uion(x,y);
		}
	}
	return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <set>
#include <algorithm>
#include <map>
#include <queue>
#include <cmath>
#include <ctime>
#include <list>
#include <sstream>
#include <string>
#include <cstring>
#include <utility>
using namespace std;
int n,m,q,parent[300005],diam[300005],deep[300005],xx,yy,ans,state;
vector <int> v[300005];

int fnd(int x)
{
	return (x==parent[x]?x:parent[x]=fnd(parent[x]));
}

void uion(int x,int y)
{
	int rotx=fnd(x);
	int roty=fnd(y);
	if (rotx!=roty)
	{
		parent[rotx]=roty;
		diam[roty]=max(max(diam[rotx],diam[roty]),((diam[rotx]+1)/2+(diam[roty]+1)/2+1));
	}
}

int dfs(int father,int x)
{
	for (int i=0;i<v[x].size();i++)
	{
		if (v[x][i]!=father)
		{
			deep[v[x][i]]=deep[x]=1;
			int nxt=dfs(x,v[x][i]);
			if (deep[nxt]>deep[ans]) ans=x;
		}
	}
	return ans;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		parent[i]=i;
	for (int i=1;i<=m;i++)
	{
		cin>>xx>>yy;
		int rotx=fnd(xx);
		int roty=fnd(yy);
		parent[rotx]=roty;
		v[xx].push_back(yy);
		v[yy].push_back(xx);
	}
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (diam[root]==0)
		{
			ans=0;
			xx=dfs(0,i);
			deep[xx]=0;
			yy=dfs(0,xx);
			diam[root]=deep[yy];
		}
	}
	for (int i=1;i<=q;i++)
	{
		cin>>state;
		if (state==1)
		{
			cin>>xx;
			cout<<diam[fnd(xx)]<<endl;
		}
		else
		{
			cin>>xx>>yy;
			int rotx=fnd(xx);
			int roty=fnd(yy);
			uion(xx,yy);
		}
	}
}


#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <sstream>
#include <cstring>
#include <bitset>
#include <stack>
using namespace std;
int n,m,q,p[300005],rank[300005],path[300005],diam[300005],dis[300005];
vector <int> v[300005];

int fnd(int x)
{
	return (p[x]==x?x:p[x]=fnd(p[x]));
}

inline void uion(int x,int y)
{
	int rootx=fnd(x);
	int rooty=fnd(y);
	if (rootx==rooty) return;
	p[rootx]=rooty;
	diam[rooty]=max(max(diam[rootx],diam[rooty]),((diam[rootx]+1)/2+(diam[rooty]+1)/2+1));
}

int dfs(int par,int x)
{
	int res=x;
	for (int i=0;i<v[x].size();i++)
	{
		int tx=v[x][i];
		if (par!=tx)
		{
			dis[tx]=dis[x]+1;
			int tmp=dfs(x,tx);
			if (dis[tmp]>dis[res]) res=tmp;
		}
	}
	return res;
}

int main()
{
	cin>>n>>m>>q;
	for (int i=1;i<=n;i++)
		p[i]=i;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		uion(x,y);
		v[x].push_back(y);
		v[y].push_back(x);
	}
	memset(diam,0,sizeof(diam));
	for (int i=1;i<=n;i++)
	{
		int root=fnd(i);
		if (!diam[root])
		{
			int id=dfs(0,root);
			dis[id]=0;
			diam[root]=dis[dfs(0,id)];
//			cout<<root<<" "<<id<<" "<<diam[root]<<endl;
		}
	}
	for (int i=1;i<=q;i++)
	{
		int type,x,y;
		cin>>type;
		if (type==1)
		{
			cin>>x;
			cout<<diam[fnd(x)]<<endl;
		}
		else
		{
			cin>>x>>y;
			uion(x,y);
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return pset[v] = findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (x == y) return;
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     freopen("in.inp","r",stdin);
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(i);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(i);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(p);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(p);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)];
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return pset[v] = findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (x == y) return;
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     //freopen("in.inp","r",stdin);
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(i);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];

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;
}

void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return pset[v] = findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (x == y) return;
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
   //  freopen("in.inp","r",stdin);
     n = nextInt();
     m = nextInt();
     q = nextInt();
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          u = nextInt();
          v = nextInt();
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(i);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          qq = nextInt();
          if (qq == 1)
          {
               int x;
               x = nextInt();
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               x = nextInt();
               y = nextInt();
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];
void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] >= sz[y]) swap(x,y);
     pset[x] = y;
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     cin >> n >> m >> q;
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          cin >> u >> v;
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(p);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          cin >> qq;
          if (qq == 1)
          {
               int x;
               cin >> x;
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               cin >> x >> y;
               unionSet_query(x,y);
          }
     }
}


#include <bits/stdc++.h>
using namespace std;
vector <int> adj[300300];
int m,n,q;
int pset[300300];
int sz[300300];
int longest[300300];
int used[300300];

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;
}

void initSet(int n)
{
     for (int i = 1;i <= n;i++) {pset[i] = i;sz[i] = 1;longest[i] = 0;}
}
int findSet(int v)
{
     if (pset[v] == v) return v; else return pset[v] = findSet(pset[v]);
}
void unionSet(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
}

int rad(int x)
{
    return (longest[x] + 1) / 2;
}
void unionSet_query(int u, int v)
{
     int x = findSet(u);
     int y = findSet(v);
     if (x == y) return;
     if (sz[x] > sz[y]) swap(x,y);
     pset[x] = y;
     sz[y] += sz[x];
     longest[y] = max(max(longest[x],longest[y]),rad(x) + rad(y) + 1);
}
int maxi, maxiV;
void dfs(int v, int depth, int p)
 {
    if (depth > maxi)
    {
        maxi = depth;
        maxiV = v;
    }
    for (int i = 0; i < adj[v].size(); i++)
    {
        int to = adj[v][i];
        if (to != p) dfs(to, depth + 1, v);
    }
}

int longest_way(int v)
 {
    maxi = -1;
    dfs(v, 0, -1);
    maxi = -1;
    dfs(maxiV, 0, -1);
    return maxi;
}
int main ()
{
     freopen("in.inp","r",stdin);
     n = nextInt();
     m = nextInt();
     q = nextInt();
     initSet(n);
     for (int i = 1;i <= m;i++)
     {
          int u, v;
          u = nextInt();
          v = nextInt();
          adj[u].push_back(v);
          adj[v].push_back(u);
          unionSet(u,v);
     }
     for (int i = 1;i <= n;i++)
     {
          int p = pset[i];
          if (!used[p])
          {
               used[p] = 1;
               longest[p] = longest_way(i);
          }
     }
     for (int i = 1;i <= q;i++)
     {
          int qq;
          qq = nextInt();
          if (qq == 1)
          {
               int x;
               x = nextInt();
               cout << longest[findSet(x)] << endl;
          }
          else if (qq == 2)
          {
               int x,y;
               x = nextInt();
               y = nextInt();
               unionSet_query(x,y);
          }
     }
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
        ans[y]=max(ans[y],(ans[x]+1)/2+(ans[y]+1)/2+1);
    }
    else
    {
        pre[y]=x;
        ans[x]=max(ans[x],(ans[x]+1)/2+(ans[y]+1)/2+1);
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        //unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    memset(vis,false,sizeof(vis));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            dfs(findd(i),0);
            t=-1;
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int maxn = 3 * 1e5 + 5;
int N, M, Q, f[maxn], s[maxn];
int root, ans, rec;
vector<int> g[maxn];

int getfar(int x) {
    return f[x] == x ? x : f[x] = getfar(f[x]);
}

void link (int u, int v) {
    int x = getfar(u);
    int y = getfar(v);

    if (x == y)
        return;

    if (s[x] < s[y])
        swap(s[x], s[y]);

    f[y] = x;
    s[x] = max(s[x], (s[x] + 1) / 2 + (s[y] + 1) / 2 + 1);
}

void dfs (int u, int p, int d) {
    f[u] = root;

    if (d > ans) {
        ans = d;
        rec = u;
    }

    for (int i = 0; i < g[u].size(); i++) {
        if (g[u][i] != p)
            dfs(g[u][i], u, d+1);
    }
}

int main () {
    int type, u, v;

    scanf("%d%d%d", &N, &M, &Q);
    for (int i = 1; i <= N; i++) {
        f[i] = i;
        g[i].clear();
    }

    for (int i = 0; i < M; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    for (int i = 1; i <= N; i++) {
        if (f[i] == i) {
            root = rec = i;
            ans = -1;
            dfs(i, 0, 0);

            ans = -1;
            dfs(rec, 0, 0);
            s[i] = ans;
        }
    }

    for (int i = 0; i < Q; i++) {
        scanf("%d", &type);
        if (type == 1) {
            scanf("%d", &u);
            v = getfar(u);
            printf("%d\n", s[v]);
        } else {
            scanf("%d%d", &u, &v);
            link(u, v);
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ans[300001];
int vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    pre[x]=y;
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    if (x<vis[s])
        return;
    vis[s]=x;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        dfs(d,x+1);
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
        pre[x]=y;
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(ans[findd(a)],(omax-omax/2)+(omin-omin/2)+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
        pre[x]=y;
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(ans[findd(a)],(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
        pre[x]=y;
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=(omax-omax/2)+omin+1;
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
        ans[y]=max(ans[y],(ans[x]+1)/2+(ans[y]+1)/2+1);
    }
    else
    {
        pre[y]=x;
        ans[x]=max(ans[x],(ans[x]+1)/2+(ans[y]+1)/2+1);
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        //unite(a,b);
    }
    //memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
        pre[x]=y;
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(ans[findd(a)],(omax-omax/2)+omin+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
int vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    if (x<vis[s])
        return;
    vis[s]=x;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        dfs(d,x+1);
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }//
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ans[300001];
int vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    pre[x]=y;
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    if (x<vis[s])
        return;
    vis[s]=x;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        dfs(d,x+1);
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        //ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,0,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
        ans[y]=max(ans[y],(ans[x]+1)/2+(ans[y]+1)/2+1);
    }
    else
    {
        pre[y]=x;
        ans[x]=max(ans[x],(ans[x]+1)/2+(ans[y]+1)/2+1);
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    //memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(ans[findd(a)],(ans[findd(a)]+1)/2+(ans[findd(b)]+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (!vis[d])
            dfs(d,x+1);
    }
    vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(findd(i),0);
            t=-1;
            memset(vis,false,sizeof(vis));
            dfs(tp,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(ans[findd(a)],(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int n,m,q,t,tp;
int pre[300001],ran[300001],ans[300001];
bool vis[300001];
vector<int>g[300001];
int findd(int x)
{
    if (pre[x]==x)
        return x;
    else
        return pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
    x=findd(x);
    y=findd(y);
    if (x==y)
        return;
    if (ran[x]<ran[y])
    {
        pre[x]=y;
    }
    else
    {
        pre[y]=x;
        if (ran[x]==ran[y])
            ran[x]++;
    }
}
bool same(int x,int y)
{
    return findd(x)==findd(y);
}
void dfs(int s,int pp,int x)
{
    if (x>t)
    {
        t=x;
        tp=s;
    }
    //vis[s]=true;
    for (int i=0;i<g[s].size();i++)
    {
        int d=g[s][i];
        if (pp!=d)
            dfs(d,s,x+1);
    }
    //vis[s]=false;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=n;i++)
    {
        pre[i]=i;
        ran[i]=0;
        g[i].clear();
    }
    for (int i=0;i<m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        g[b].push_back(a);
        unite(a,b);
    }
    memset(ans,-1,sizeof(ans));
    for (int i=1;i<=n;i++)
    {
        if (ans[findd(i)]==-1)
        {
            t=-1;
            //memset(vis,false,sizeof(vis));
            dfs(findd(i),0,0);
            t=-1;
            //memset(vis,false,sizeof(vis));
            dfs(tp,0,0);
            ans[findd(i)]=t;
        }
    }
    while (q--)
    {
        int w;
        scanf("%d",&w);
        if (w==1)
        {
            int a;
            scanf("%d",&a);
            printf("%d\n",ans[findd(a)]);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int omax=max(ans[findd(a)],ans[findd(b)]);
            int omin=min(ans[findd(a)],ans[findd(b)]);
            if (!same(a,b))
            {
                unite(a,b);
                ans[findd(a)]=max(omax,(omax+1)/2+(omin+1)/2+1);
            }
        }
    }
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1);
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1);
	}
}

vector<int> G[N];
int vis[N];
int DP[N];
int diam;
void dfs(int u, int p = -1){
	vis[u] = 1;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		dfs(nxt);
	}
	vector<int> mx;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (nxt == p) continue;
		mx.push_back(DP[nxt]);
	}
	sort(mx.begin(), mx.end(), greater<int>());
	int mx1 = 0, mx2 = 0;
	if (mx.size() > 0) mx1 = mx[0];
	if (mx.size() > 1) mx2 = mx[1];
	diam = max(diam, mx1 + mx2);
	DP[u] = mx1 + 1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);

	init();
	int n, m, q; cin >> n >> m >> q;
	for (int i = 0; i < m; i++){
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = -1;
		dfs(i);
		ans[findSet(i)] = diam;
	}
	for (int i = 0; i < q; i++){
		int type; cin >> type;
		if (type == 1){
			int x; cin >> x;
			cout << ans[findSet(x)] << endl;
		}
		else{
			int x, y; cin >> x >> y;
			mergeQ(x, y);
		}
	}

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], max(ans[x], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1));
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], max(ans[y], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1));
	}
}

vector<int> G[N];
int vis[N];
int DP[N];
int diam;
void dfs(int u, int p = -1){
	vis[u] = 1;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		dfs(nxt);
	}
	vector<int> mx;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (nxt == p) continue;
		mx.push_back(DP[nxt]);
	}
	sort(mx.begin(), mx.end(), greater<int>());
	int mx1 = 0, mx2 = 0;
	if (mx.size() > 0) mx1 = mx[0];
	if (mx.size() > 1) mx2 = mx[1];
	diam = max(diam, mx1 + mx2);
	DP[u] = mx1 + 1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	//ios::sync_with_stdio(0);
	//cin.tie(0);

	init();
	int n, m, q; scanf("%d%d%d", &n, &m, &q);
	for (int i = 0; i < m; i++){
		int a, b; scanf("%d%d", &a, &b);
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = 0;
		dfs(i);
		ans[findSet(i)] = diam;
	}
	for (int i = 0; i < q; i++){
		int type; scanf("%d", &type);
		if (type == 1){
			int x; scanf("%d", &x);
			printf("%d\n", ans[findSet(x)]);
		}
		else{
			int x, y; scanf("%d%d", &x, &y);
			mergeQ(x, y);
		}
	}

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], max(ans[x], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1));
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], max(ans[y], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1));
	}
}

vector<int> G[N];
int vis[N];
int DP[N];
int diam;
void dfs(int u, int p = -1){
	vis[u] = 1;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		dfs(nxt);
	}
	vector<int> mx;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (nxt == p) continue;
		mx.push_back(DP[nxt]);
	}
	sort(mx.begin(), mx.end(), greater<int>());
	int mx1 = 0, mx2 = 0;
	if (mx.size() > 0) mx1 = mx[0];
	if (mx.size() > 1) mx2 = mx[1];
	diam = max(diam, mx1 + mx2);
	DP[u] = mx1 + 1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);

	init();
	int n, m, q; cin >> n >> m >> q;
	for (int i = 0; i < m; i++){
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = 0;
		dfs(i);
		ans[findSet(i)] = diam;
	}
	for (int i = 0; i < q; i++){
		int type; cin >> type;
		if (type == 1){
			int x; cin >> x;
			cout << ans[findSet(x)] << endl;
		}
		else{
			int x, y; cin >> x >> y;
			mergeQ(x, y);
		}
	}

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

int isSameSet(int u, int v){
	return (findSet(u) == findSet(v));
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], (ans[x] + 2) / 2 + (ans[y] + 2) / 2);
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], (ans[x] + 2) / 2 + (ans[y] + 2) / 2);
	}
}

vector<int> G[N];
int vis[N];
int diam;
int dfs(int u){
	vis[u] = 1;
	int mx1 = 0, mx2 = 0;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		int val = dfs(nxt);
		if (val > mx2) val = mx2;
		if (mx2 > mx1) swap(mx1, mx2);
	}
	diam = max(diam, mx1 + mx2 + 1);
	return mx1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);

	init();
	int n, m, q; cin >> n >> m >> q;
	for (int i = 0; i < m; i++){
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = -1;
		dfs(i);
		ans[findSet(i)] = diam;
	}
	for (int i = 0; i < q; i++){
		int type; cin >> type;
		if (type == 1){
			int x; cin >> x;
			cout << ans[findSet(x)] - 1 << endl;
		}
		else{
			int x, y; cin >> x >> y;
			mergeQ(x, y);
		}
	}

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

int isSameSet(int u, int v){
	return (findSet(u) == findSet(v));
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], (ans[x] + 2) / 2 + (ans[y] + 2) / 2);
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], (ans[x] + 2) / 2 + (ans[y] + 2) / 2);
	}
}

vector<int> G[N];
int vis[N];
int diam;
int dfs(int u){
	vis[u] = 1;
	int mx1 = 0, mx2 = 0;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		int val = dfs(nxt);
		if (val > mx2) mx2 = val;
		if (mx2 > mx1) swap(mx1, mx2);
	}
	diam = max(diam, mx1 + mx2 + 1);
	return mx1 + 1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);

	init();
	int n, m, q; cin >> n >> m >> q;
	for (int i = 0; i < m; i++){
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = -1;
		dfs(i);
		ans[findSet(i)] = diam;
	}
	for (int i = 0; i < q; i++){
		int type; cin >> type;
		if (type == 1){
			int x; cin >> x;
			cout << ans[findSet(x)] - 1 << endl;
		}
		else{
			int x, y; cin >> x >> y;
			mergeQ(x, y);
		}
	}

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits\stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pp;
#define N 300100

int par[N];
int rnk[N];
int ans[N];

void init(){
	for (int i = 0; i < N; i++) par[i] = i, rnk[i] = 0;
}

int findSet(int u){
	if (par[u] == u) return u;
	return par[u] = findSet(par[u]);
}

void merge(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]) par[x] = y;
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
	}
}

void mergeQ(int u, int v){
	int x = findSet(u), y = findSet(v);
	if (x == y) return;
	if (rnk[x] < rnk[y]){
		par[x] = y;
		ans[y] = max(ans[y], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1);
	}
	else{
		par[y] = x;
		if (rnk[x] == rnk[y]) rnk[x]++;
		ans[x] = max(ans[x], (ans[x] + 1) / 2 + (ans[y] + 1) / 2 + 1);
	}
}

vector<int> G[N];
int vis[N];
int diam;
int dfs(int u){
	vis[u] = 1;
	int mx1 = 0, mx2 = 0;
	for (int i = 0; i < G[u].size(); i++){
		int nxt = G[u][i];
		if (vis[nxt]) continue;
		int val = dfs(nxt);
		if (val > mx2) mx2 = val;
		if (mx2 > mx1) swap(mx1, mx2);
	}
	diam = max(diam, mx1 + mx2 + 1);
	return mx1 + 1;
}

int main(){
	//freopen("in.in", "r", stdin);
	//freopen("out.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);

	init();
	int n, m, q; cin >> n >> m >> q;
	for (int i = 0; i < m; i++){
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
		merge(a, b);
	}
	for (int i = 1; i <= n; i++){
		if (vis[i]) continue;
		diam = -1;
		dfs(i);
		ans[findSet(i)] = diam - 1;
	}
	for (int i = 0; i < q; i++){
		int type; cin >> type;
		if (type == 1){
			int x; cin >> x;
			cout << ans[findSet(x)] << endl;
		}
		else{
			int x, y; cin >> x >> y;
			mergeQ(x, y);
		}
	}

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>

#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define EPS 1e-7

#define pii pair<int,int>
#define FFF freopen("test","r",stdin)
#define all(a) a.begin(),a.end()

#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define FORL0(i,a) for(i=a;i>=0;i--)
#define FORL1(i,a) for(i=a;i>=1;i--)
#define FORL(i,a,b)for(i=a;i>=b;i--)

#define rush() int _CC;for(scanf("%d",&_CC);_CC--;)
#define Rush(n)  while(scanf("%d",&n)!=-1)
using namespace std;

void RD(int &x){scanf("%d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}

void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(u32 x) {printf("%u\n",x);}
void PR(u64 x) {cout<<x<<endl;}
void PR(double x) {printf("%.4lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}
void PR(i64 x) {cout<<x<<endl;}

void upMin(int &x,int y) {if(x>y) x=y;}
void upMin(i64 &x,i64 y) {if(x>y) x=y;}
void upMin(double &x,double y) {if(x>y) x=y;}
void upMax(int &x,int y) {if(x<y) x=y;}
void upMax(i64 &x,i64 y) {if(x<y) x=y;}
void upMax(double &x,double y) {if(x<y) x=y;}

int sgn(double x)
{
    if(x>1e-10) return 1;
    if(x<-1e-10) return -1;
    return 0;
}

i64 Gcd(i64 x,i64 y)
{
    if(x<0) x=-x;
    if(y<0) y=-y;
    if(y==0) return x;
    return Gcd(y,x%y);
}

i64 Lcm(i64 x,i64 y)
{
    return x/Gcd(x,y)*y;
}

i64 eular(i64 n)
{
    i64 ans=n,i;
    for(i=2;i*i<=n;i++) if(n%i==0)
    {
        ans-=ans/i;
        while(n%i==0) n/=i;
    }
    if(n>1) ans-=ans/n;
    return ans;
}

i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    i64 temp=exGcd(b,a%b,x,y);
    i64 t=x;
    x=y;
    y=t-a/b*y;
    return temp;
}

i64 gcdReverse(i64 a,i64 b)
{
    i64 x,y;
    i64 g=exGcd(a,b,x,y);
    if(g!=1) return 0;
    x%=b;
    if(x<0) x+=b;
    return x;
}

i64 myPow(i64 a,i64 b)
{
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}

i64 myPow(i64 a,i64 b,i64 mod)
{
    a%=mod;
    i64 ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

i64 getInt()
{
    i64 x=0,flag=1;
    char c=getchar();
    while(!isdigit(c)&&c!='-') c=getchar();
    if(c=='-')
    {
        flag=-1,c=getchar();
        while(!isdigit(c)) c=getchar();
    }
    while(isdigit(c))
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*flag;
}

i64 getSqrt(i64 t)
{
    i64 p=sqrt(1.0*t);
    while(p*p>t) p--;
    while((p+1)<=t/(p+1)) p++;
    return p;
}

struct point
{
    double x,y;

    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void get()
    {
        scanf("%lf%lf",&x,&y);
    }

    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }

    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }

    point operator*(double t)
    {
        return point(x*t,y*t);
    }

    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }

    double operator^(point a)
    {
        return x*a.x+y*a.y;
    }

    double Len()
    {
        return sqrt(x*x+y*y);
    }

    point adjustTo(double L)
    {
        L/=Len();
        return point(x*L,y*L);
    }

    point operator/(double t)
    {
        return point(x/t,y/t);
    }

    double rotateAngle(point a)
    {
        point p=*this;
        return atan2(p*a,p^a);
    }

    int operator==(point a)
    {
        return sgn(x-a.x)==0&&sgn(y-a.y)==0;
    }

    point zhuanNi(double ang)
    {
        return point(x*cos(ang)-y*sin(ang),x*sin(ang)+y*cos(ang));
    }

    point zhuanShun(double ang)
    {
        return point(x*cos(ang)+y*sin(ang),-x*sin(ang)+y*cos(ang));
    }

    void print()
    {
        printf("%.4lf %.4lf\n",x,y);
    }
};

double calPloyArea(point a[],int n)
{
    double ans=0;
    int i;
    for(i=0;i<n;i++) ans+=a[i]*a[(i+1)%n];
    return ans;
}

int changeToClockwise(point a[],int n)
{
    double s=calPloyArea(a,n);
    if(sgn(s)>=0) return 0;
    int L=0,R=n-1;
    while(L<R) swap(a[L++],a[R--]);
    return 1;
}

int pointOnSeg(point p,point a,point b)
{
    if(sgn((p-a)*(p-b))) return 0;
    int x=sgn((p.x-a.x)*(p.x-b.x));
    int y=sgn((p.y-a.y)*(p.y-b.y));
    return x<=0&&y<=0;
}

int pointOnRightOfLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))>0;
}

int pointOnLine(point p,point a,point b)
{
    return sgn((p-a)*(b-a))==0;
}

int pointOnLeftOfLine(point p,point a,point b)
{
    return sgn((b-a)*(p-a))>0;
}

/**
 *out: 1
 * on: 0
 * in: -1
 * */
int getRelationOfPointAndPloy(point a[],int n,point p)
{
    a[n]=a[0];
    int i;
    double sum=0;
    for(i=0;i<n;i++)
    {
        if(pointOnSeg(p,a[i],a[i+1])) return 0;
        point aa=a[i]-p;
        point bb=a[i+1]-p;
        sum+=aa.rotateAngle(bb);
    }

    if(fabs(sum-2*PI)<1e-2) return -1;
    return 1;
}

int isParal(point a,point b,point p,point q)
{
    double aa=(b.x-a.x)*(p.y-q.y);
    double bb=(b.y-a.y)*(p.x-q.x);
    return sgn(aa-bb)==0;
}

/**
 * 1: only one cross
 * 0: no cross
 * 2: many cross
 *
 * */
int lineCrossLine(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        return 2;
    }

    double s1=(p-a)*(q-a);
    double s2=(q-b)*(p-b);
    ans=(a*s2+b*s1)/(s1+s2);
    return 1;

}

/**
 * 1: only one cross point and store in ans
 * 0: no cross point
 * 2: many cross point
 * */

int segCrossSeg(point a,point b,point p,point q,point &ans)
{
    if(isParal(a,b,p,q))
    {
        if(!pointOnLine(p,a,b)) return 0;
        if(sgn(a.x-b.x)==0)
        {
            if(p.y>q.y) swap(p,q);
            if(a.y>b.y) swap(a,b);
            if(sgn(q.y-a.y)==-1||sgn(b.y-p.y)==-1) return 0;
            if(q==a||p==b)
            {
                if(q==a) ans=q;
                if(p==b) ans=p;
                return 1;
            }
            return 2;
        }
        if(p.x>q.x) swap(p,q);
        if(a.x>b.x) swap(a,b);
        if(sgn(q.x-a.x)==-1||sgn(b.x-p.x)==-1) return 0;
        if(q==a||p==b)
        {
            if(q==a) ans=q;
            if(p==b) ans=p;
            return 1;
        }
        return 2;
    }
    lineCrossLine(a,b,p,q,ans);
    if(pointOnSeg(ans,a,b)&&pointOnSeg(ans,p,q)) return 1;
    return 0;
}

const int SIZE=700;
const int MM=1000000000;

struct BigNum
{

    i64 a[SIZE];

    int len;

    BigNum()
    {
        clr(a,0);
    }

    BigNum(char *s,int n)
    {
        clr(a,0);
        int p=0;
        int i;
        for(i=n-1;i>=0;i-=9)
        {
            int j=max(0,i-8);
            a[p]=0;
            int k;
            for(k=j;k<=i;k++) a[p]=a[p]*10+s[k]-'0';
            p++;
        }
        adjust();
    }

    BigNum(i64 n)
    {
        clr(a,0);
        a[0]=n;
        adjust();
    }

    BigNum adjust()
    {
        int i;
        FOR0(i,SIZE)
        {
            if(a[i]>=MM)
            {
                a[i+1]+=a[i]/MM;
                a[i]%=MM;
            }
            else if(a[i]<0)
            {
                a[i+1]--;
                a[i]+=MM;
            }
        }
        for(i=SIZE-1;i>=0;i--) if(a[i]) break;
        len=i+1;
        if(len==0) len=1;
    }

    BigNum operator*(const BigNum &p)
    {
        BigNum c;
        int i,j;
        FOR0(i,len) for(j=0;j<p.len;j++)
        {
            c.a[i+j]+=a[i]*p.a[j];
        }
        c.adjust();
        return c;
    }

    BigNum operator/(const int x)
    {
        i64 tmp=0;
        BigNum c;
        memcpy(c.a,a,sizeof(a));
        int i;
        for(i=len-1;i>=0;i--)
        {
            i64 p=(tmp*MM+c.a[i])%x;
            c.a[i]=(tmp*MM+c.a[i])/x;
            tmp=p;
        }
        c.adjust();
        return c;
    }

    BigNum operator+(BigNum &p)
    {
        BigNum c;
        int i;
        int t=max(len,p.len);
        FOR0(i,t) c.a[i]=a[i]+p.a[i];
        c.adjust();
        return c;
    }

    BigNum operator-(const BigNum &p) const
    {
        BigNum c;
        int i;
        FOR0(i,len) c.a[i]=a[i]-p.a[i];
        c.adjust();
        return c;
    }

    int operator==(const BigNum &p) const
    {
        if(len!=p.len) return 0;
        int i;
        FOR0(i,SIZE) if(a[i]!=p.a[i]) return 0;
        return 1;
    }

    int operator<(const BigNum &p) const
    {
        if(len<p.len) return 1;
        if(len>p.len) return 0;
        int i;
        for(i=len-1;i>=0;i--)
        {
            if(a[i]<p.a[i]) return 1;
            if(a[i]>p.a[i]) return 0;
        }
        return 0;
    }

    int operator>(const BigNum &p) const
    {
        if(len>p.len) return 1;
        if(len<p.len) return 0;
        int i;
        for(i=len-1;i>=0;i--)
        {
            if(a[i]>p.a[i]) return 1;
            if(a[i]<p.a[i]) return 0;
        }
        return 0;
    }

    void output()
    {
        int i;
        printf("%d",(int)a[len-1]);
        for(i=len-2;i>=0;i--) printf("%09d",(int)a[i]);
        puts("");
    }
};

const i64 inf=(((i64)1)<<61)+5;
const double dinf=1e20;
const int INF=1000000005;
const int N=100005;

vector<int> g[N];
int n;
int S[N];

int m,Q;
int a[N];

int f[N],Max;
int fa[N];

int bfs(int u)
{
	queue<int> Q;
	Q.push(u);
	int i;
	f[u]=0;
	Max=0;
	int ans=u;
	while(!Q.empty())
	{
		int u=Q.front();
		Q.pop();

		int i;
		FOR0(i,SZ(g[u]))
		{
			int v=g[u][i];
			if(v==fa[u]) continue;
			fa[v]=u;
			f[v]=f[u]+1;
			if(Max<f[v]) Max=f[v],ans=v;

			Q.push(v);
		}
	}
	return ans;
}

int cal(int u)
{

	int x=bfs(u);

	PR(x);
	int y=bfs(x);
	PR(u,Max);
	return Max;
}

int get(int x)
{
	if(S[x]!=x) S[x]=get(S[x]);
	return S[x];
}

int cal(int x,int y)
{
	if(x==0) return 1;

	int x1=(x+1)/2,x2=x/2;
	int y1=(y+1)/2,y2=y/2;

	return x1+y1+1;

}

int main()
{
//	FFF;

	RD(n,m,Q);
	int i;
	FOR1(i,n) S[i]=i,a[i]=0;
	FOR1(i,m)
	{
		int x=getInt();
		int y=getInt();
		x=get(x);
		y=get(y);

		int xx=a[x];
		int yy=a[y];
		S[x]=y;
		a[y]=cal(xx,yy);

		g[x].pb(y);
		g[y].pb(x);
	}

	while(Q--)
	{
		int op;
		RD(op);
		if(op==1)
		{
			int x=getInt();
			x=get(x);
			PR(a[x]);
		}
		else
		{
			int x=getInt();
			int y=getInt();
			x=get(x);
			y=get(y);
			if(x==y) continue;
			S[x]=y;
			int xx=a[x],yy=a[y];

			if(xx<yy) swap(xx,yy);
			a[y]=cal(xx,yy);
		}
	}
}