#include<stdio.h>
#include<string.h>
long long map[510][510];
long long vish[510];
long long viss[510];
long long visx[5];
int main()
{
    int n,x,y;
    long long num,num0;
    while(~scanf("%d",&n))
    {
        num=0,num0=0;
        memset(vish,0,sizeof(vish));
        memset(visx,0,sizeof(visx));
        memset(viss,0,sizeof(viss));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%lld",&map[i][j]);
                if(map[i][j]==0)
                {
                    x=i;
                    y=j;
                }
            }
        }
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            num0+=map[x][i];
        }
        for(int i=1; i<=n; i++) //先选出一个基准数
        {
            if(i!=x)
            {
                for(int j=1;j<=n;j++)
                {
                    num+=map[i][j];
                }
                break;
            }
        }
        if(map[x][y]<=0)
        {
            printf("-1\n");
            continue;
        }
        map[x][y]=num-num0;//将空的数填上
        //printf("%lld %lld\n",map[x][y],num);
        visx[1]=0,visx[2]=0;
        int flag=0;
        for(int i=1,j=n; i<=n,j>=1; i++,j--)  //求对角线
        {
            visx[1]+=map[i][i];
            visx[2]+=map[i][j];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                viss[i]+=map[j][i];//求每竖列值
                vish[i]+=map[i][j];//求每横列值
            }
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(viss[i]!=num||vish[i]!=num)
            {
                //printf("%lld %lld\n",viss[i],vish[i]);
                flag=1;
                printf("-1\n");
                break;
            }
        }
        if(visx[1]!=num&&flag==0||visx[2]!=num&&flag==0)
        {
            flag=1;
            printf("-1\n");
            continue;
        }
        if(flag==0)
        {
            printf("%lld\n",map[x][y]);
        }
    }
}


#include<stdio.h>
#include<string.h>
long long map[510][510];
long long vish[510];
long long viss[510];
long long visx[5];
int main()
{
    int n,x,y;
    long long num,num0;
    while(~scanf("%d",&n))
    {
        num=0,num0=0;
        memset(vish,0,sizeof(vish));
        memset(visx,0,sizeof(visx));
        memset(viss,0,sizeof(viss));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%lld",&map[i][j]);
                if(map[i][j]==0)
                {
                    x=i;
                    y=j;
                }
            }
        }
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            num0+=map[x][i];
        }
        for(int i=1; i<=n; i++) //先选出一个基准数
        {
            if(i!=x)
            {
                for(int j=1;j<=n;j++)
                {
                    num+=map[i][j];
                }
                break;
            }
        }
        map[x][y]=num-num0;//将空的数填上
        //printf("%lld %lld\n",map[x][y],num);
        visx[1]=0,visx[2]=0;
        int flag=0;
        for(int i=1,j=n; i<=n,j>=1; i++,j--)  //求对角线
        {
            visx[1]+=map[i][i];
            visx[2]+=map[i][j];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                viss[i]+=map[j][i];//求每竖列值
                vish[i]+=map[i][j];//求每横列值
            }
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(viss[i]!=num||vish[i]!=num)
            {
                //printf("%lld %lld\n",viss[i],vish[i]);
                flag=1;
                printf("-1\n");
                break;
            }
        }
        if(visx[1]!=num&&flag==0||visx[2]!=num&&flag==0)
        {
            flag=1;
            printf("-1\n");
            continue;
        }
        if(flag==0)
        {
            printf("%lld\n",map[x][y]);
        }
    }
}


#include<stdio.h>
#include<string.h>
long long map[510][510];
long long vish[510];
long long viss[510];
long long visx[5];
int main()
{
    int n,x,y;
    long long num,num0;
    while(~scanf("%d",&n))
    {
        num=0,num0=0;
        memset(vish,0,sizeof(vish));
        memset(visx,0,sizeof(visx));
        memset(viss,0,sizeof(viss));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%lld",&map[i][j]);
                if(map[i][j]==0)
                {
                    x=i;
                    y=j;
                }
            }
        }
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            num0+=map[x][i];
        }
        for(int i=1; i<=n; i++) //先选出一个基准数
        {
            if(i!=x)
            {
                for(int j=1;j<=n;j++)
                {
                    num+=map[i][j];
                }
                break;
            }
        }
        map[x][y]=num-num0;//将空的数填上
        if(map[x][y]<=0)
        {
            printf("-1\n");
            continue;
        }
        //printf("%lld %lld\n",map[x][y],num);
        visx[1]=0,visx[2]=0;
        int flag=0;
        for(int i=1,j=n; i<=n,j>=1; i++,j--)  //求对角线
        {
            visx[1]+=map[i][i];
            visx[2]+=map[i][j];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                viss[i]+=map[j][i];//求每竖列值
                vish[i]+=map[i][j];//求每横列值
            }
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(viss[i]!=num||vish[i]!=num)
            {
                //printf("%lld %lld\n",viss[i],vish[i]);
                flag=1;
                printf("-1\n");
                break;
            }
        }
        if(visx[1]!=num&&flag==0||visx[2]!=num&&flag==0)
        {
            flag=1;
            printf("-1\n");
            continue;
        }
        if(flag==0)
        {
            printf("%lld\n",map[x][y]);
        }
    }
}


#include<stdio.h>
#include<string.h>
long long map[510][510];
long long vish[510];
long long viss[510];
long long visx[5];
int main()
{
    int n,x,y;
    long long num,num0;
    while(~scanf("%d",&n))
    {
        num=0,num0=0;
        memset(vish,0,sizeof(vish));
        memset(visx,0,sizeof(visx));
        memset(viss,0,sizeof(viss));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%lld",&map[i][j]);
                if(map[i][j]==0)
                {
                    x=i;
                    y=j;
                }
            }
        }
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        for(int i=1;i<=n;i++)
        {
            num0+=map[x][i];
        }
        for(int i=1; i<=n; i++) //先选出一个基准数
        {
            if(i!=x)
            {
                for(int j=1;j<=n;j++)
                {
                    num+=map[i][j];
                }
                break;
            }
        }
        if(map[i][j]<=0)
        {
            printf("-1\n");
            continue;
        }
        map[x][y]=num-num0;//将空的数填上
        //printf("%lld %lld\n",map[x][y],num);
        visx[1]=0,visx[2]=0;
        int flag=0;
        for(int i=1,j=n; i<=n,j>=1; i++,j--)  //求对角线
        {
            visx[1]+=map[i][i];
            visx[2]+=map[i][j];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                viss[i]+=map[j][i];//求每竖列值
                vish[i]+=map[i][j];//求每横列值
            }
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(viss[i]!=num||vish[i]!=num)
            {
                //printf("%lld %lld\n",viss[i],vish[i]);
                flag=1;
                printf("-1\n");
                break;
            }
        }
        if(visx[1]!=num&&flag==0||visx[2]!=num&&flag==0)
        {
            flag=1;
            printf("-1\n");
            continue;
        }
        if(flag==0)
        {
            printf("%lld\n",map[x][y]);
        }
    }
}


#include<stdio.h>
#include<string.h>
long long map[510][510];
long long vish[510];
long long viss[510];
long long visx[5];
int main()
{
    int n,x,y;
    long long num,num0;
    while(~scanf("%d",&n))
    {
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        num=0,num0=0;
        memset(vish,0,sizeof(vish));
        memset(visx,0,sizeof(visx));
        memset(viss,0,sizeof(viss));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%lld",&map[i][j]);
                if(map[i][j]==0)
                {
                    x=i;
                    y=j;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            num0+=map[x][i];
        }
        for(int i=1; i<=n; i++) //先选出一个基准数
        {
            if(i!=x)
            {
                for(int j=1;j<=n;j++)
                {
                    num+=map[i][j];
                }
                break;
            }
        }
        map[x][y]=num-num0;//将空的数填上
        //printf("%lld %lld\n",map[x][y],num);
        visx[1]=0,visx[2]=0;
        int flag=0;
        for(int i=1,j=n; i<=n,j>=1; i++,j--)  //求对角线
        {
            visx[1]+=map[i][i];
            visx[2]+=map[i][j];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                viss[i]+=map[j][i];//求每竖列值
                vish[i]+=map[i][j];//求每横列值
            }
        }
        flag=0;
        for(int i=1;i<=n;i++)
        {
            if(viss[i]!=num||vish[i]!=num)
            {
                //printf("%lld %lld\n",viss[i],vish[i]);
                flag=1;
                printf("-1\n");
                break;
            }
        }
        if(visx[1]!=num&&flag==0||visx[2]!=num&&flag==0)
        {
            flag=1;
            printf("-1\n");
            continue;
        }
        if(flag==0)
        {
            printf("%lld\n",map[x][y]);
        }
    }
}


//Very Important Always rember using (unsigned long long int) is very dangerous.
//Operation ull int's always yield positive number like 93 - 102 = (some positive number).
#include<stdio.h>
long long int magic[509][509]= {0};
long long int N;
long long int a,b;
long long int sum = 0,find = 0;
long long int check_row(long long int x){
	 unsigned long long int sum1= 0;
	 unsigned long long int i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[x][i];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int check_cln(long long int x){
	 unsigned long long int sum1= 0,i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[i][x];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int main(){
	scanf("%I64d",&N);
	long long int i,j;
	for(i = 1 ; i <= N ; i++){
		for(j = 1 ; j <= N ; j++){
			scanf("%I64d",&magic[i][j]);
			if(magic[i][j] == 0){
				a = i;
				b = j;
			}
		}
	}
	long long int valid;
	for(i = 1 ; i <= N ; i++){
		if(i != a){
			valid = i;
			break;
		}
	}
	for(i = 1 ; i <= N ; i++){
		sum = sum + magic[valid][i];
	}
	for(i = 1 ; i <= N ; i++){
		find = find + magic[a][i];
	}
	long long int counter = 0;
	if((sum - find) > 0){
		magic[a][b] = sum - find;
		for(i = 1 ; i <= N ; i++){
			if(check_row(i) != 0){
				counter = -1;
				break;
			}
			if(check_cln(i) != 0){
				counter = -1;
				break;
			}
		}
		if(counter == 0){
			unsigned long long int d1 = 0,d2 = 0;
			for(i=1; i <= N ; i++){
				d1 += magic[i][i];
				d2 += magic[i][N-i+1];
			}
			if(sum != d1 || d1 != d2 || sum != d2){
				counter = -1;
			}
		}
		if(counter == 0){
			printf("%I64d\n",magic[a][b]);
		}
		else{
			printf("-1\n");
		}
	}
	else{
		if(N == 1){
			printf("1\n");
		}
		else{
			printf("-1\n");
		}
	}
}


#include<stdio.h>
unsigned long long int magic[509][509]= {0};
long long int N;
long long int a,b;
unsigned long long int sum = 0,find = 0;
long long int check_row(unsigned long long int x){
	 unsigned long long int sum1= 0;
	 unsigned long long int i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[x][i];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int check_cln( unsigned long long int x){
	 unsigned long long int sum1= 0,i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[i][x];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int main(){
	scanf("%I64d",&N);
	long long int i,j;
	for(i = 1 ; i <= N ; i++){
		for(j = 1 ; j <= N ; j++){
			scanf("%I64d",&magic[i][j]);
			if(magic[i][j] == 0){
				a = i;
				b = j;
			}
		}
	}
	long long int valid;
	for(i = 1 ; i <= N ; i++){
		if(i != a){
			valid = i;
			break;
		}
	}
	for(i = 1 ; i <= N ; i++){
		sum = sum + magic[valid][i];
	}
	for(i = 1 ; i <= N ; i++){
		find = find + magic[a][i];
	}
	long long int counter = 0;
	if(sum - find > 0){
		magic[a][b] = sum - find;
		for(i = 1 ; i <= N ; i++){
			if(check_row(i) != 0){
				counter = -1;
				break;
			}
			if(check_cln(i) != 0){
				counter = -1;
				break;
			}
		}
		if(counter == 0){
			unsigned long long int d1 = 0,d2 = 0;
			for(i=1; i <= N ; i++){
				d1 += magic[i][i];
				d2 += magic[i][N-i+1];
			}
			if(sum != d1 || d1 != d2 || sum != d2){
				counter = -1;
			}
		}
		if(counter == 0){
			printf("%I64d\n",magic[a][b]);
		}
		else{
			printf("-1\n");
		}
	}
	else{
		if(N == 1){
			printf("1\n");
		}
		else{
			printf("-1\n");
		}
	}
}


#include<stdio.h>
unsigned long long int magic[509][509]= {0};
long long int N;
long long int a,b;
unsigned long long int sum = 0,find = 0;
long long int check_row(unsigned long long int x){
	 unsigned long long int sum1= 0;
	 unsigned long long int i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[x][i];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int check_cln( unsigned long long int x){
	 unsigned long long int sum1= 0,i;
	for(i = 1 ; i <= N ; i++){
		sum1 = sum1 + magic[i][x];
	}
	if(sum1 != sum){
		return -1;
	}
	return 0;
}
int main(){
	scanf("%I64d",&N);
	long long int i,j;
	for(i = 1 ; i <= N ; i++){
		for(j = 1 ; j <= N ; j++){
			scanf("%I64d",&magic[i][j]);
			if(magic[i][j] == 0){
				a = i;
				b = j;
			}
		}
	}
	long long int valid;
	for(i = 1 ; i <= N ; i++){
		if(i != a){
			valid = i;
			break;
		}
	}
	for(i = 1 ; i <= N ; i++){
		sum = sum + magic[valid][i];
	}
	for(i = 1 ; i <= N ; i++){
		find = find + magic[a][i];
	}
	long long int counter = 0;
	if(sum - find > 0){
		magic[a][b] = sum - find;
		for(i = 1 ; i <= N ; i++){
			if(check_row(i) != 0){
				counter = -1;
				break;
			}
			if(check_cln(i) != 0){
				counter = -1;
				break;
			}
		}
		if(counter == 0){
			unsigned long long int d1 = 0,d2 = 0;
			for(i=1; i <= N ; i++){
				d1 += magic[i][i];
				d2 += magic[i][N-i+1];
			}
			if(sum != d1 || d1 != d2 || sum != d2){
				counter = -1;
			}
		}
		if(counter == 0){
			printf("%I64d\n",magic[a][b]);
		}
		else{
			printf("-1\n");
		}
	}
	else{
		printf("-1\n");
	}
}


#include <stdio.h>

int main() {
	int i, j, n, i0, j0, zero, good;
	long long sum, sum0, sum2, tmp;
	static long long a[500][500];

	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++)
			scanf("%lld", &a[i][j]);
		tmp = 0;
		zero = 0;
		for (j = 0; j < n; j++) {
			tmp += a[i][j];
			if (a[i][j] == 0) {
				i0 = i, j0 = j;
				zero = 1;
			}
		}
		if (zero)
			sum0 = tmp;
		else
			sum = tmp;
	}
	good = 1;
	a[i0][j0] = sum - sum0;
	for (i = 0; i < n; i++) {
		sum2 = 0;
		for (j = 0; j < n; j++)
			sum2 += a[i][j];
		if (sum2 != sum) {
			good = 0;
			break;
		}
	}
	for (j = 0; j < n; j++) {
		sum2 = 0;
		for (i = 0; i < n; i++)
			sum2 += a[i][j];
		if (sum2 != sum) {
			good = 0;
			break;
		}
	}
	sum2 = 0;
	for (i = 0; i < n; i++)
		sum2 += a[i][i];
	if (sum2 != sum)
		good = 0;
	sum2 = 0;
	for (i = 0; i < n; i++)
		sum2 += a[i][n - i - 1];
	if (sum2 != sum)
		good = 0;
	printf("%lld\n", !good || a[i0][j0] <= 0 || a[i0][j0] > 1e18
			? -1 : a[i0][j0]);
	return 0;
}


#include <stdio.h>

int main() {
	int i, j, n, sum, sum0, sum2, tmp, i0, j0, zero, good;
	static int a[500][500];

	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++)
			scanf("%d", &a[i][j]);
		tmp = 0;
		zero = 0;
		for (j = 0; j < n; j++) {
			tmp += a[i][j];
			if (a[i][j] == 0) {
				i0 = i, j0 = j;
				zero = 1;
			}
		}
		if (zero)
			sum0 = tmp;
		else
			sum = tmp;
	}
	good = 1;
	a[i0][j0] = sum - sum0;
	for (i = 0; i < n; i++) {
		sum2 = 0;
		for (j = 0; j < n; j++)
			sum2 += a[i][j];
		if (sum2 != sum) {
			good = 0;
			break;
		}
	}
	for (j = 0; j < n; j++) {
		sum2 = 0;
		for (i = 0; i < n; i++)
			sum2 += a[i][j];
		if (sum2 != sum) {
			good = 0;
			break;
		}
	}
	sum2 = 0;
	for (i = 0; i < n; i++)
		sum2 += a[i][i];
	if (sum2 != sum)
		good = 0;
	sum2 = 0;
	for (i = 0; i < n; i++)
		sum2 += a[i][n - i - 1];
	if (sum2 != sum)
		good = 0;
	printf("%d\n", !good || a[i0][j0] <= 0 ? -1 : a[i0][j0]);
	return 0;
}


#include<stdio.h>

int main() {
    int n;
    int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    long sums[1002];
    long diff;
    char flag = 1;

    scanf("%d", &n);
    if ( n == 1 ){
        printf("1\n");
        return 0;
    }

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            if ( diff <= 0 ) {
                printf("-1\n");
                return 0;
            }
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%ld\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include<stdio.h>

int main() {
    int n;
    unsigned int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    unsigned long long sums[1002];
    unsigned long long diff;
    char flag = 1;

    scanf("%d", &n);
    if ( n == 1 ){
        printf("1\n");
        return 0;
    }

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            if ( diff <= 0 ) {
                printf("-1\n");
                return 0;
            }
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%ld\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include<stdio.h>

int main() {
    int n;
    int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    long sums[1002];
    long diff;
    char flag = 1;

    scanf("%d", &n);
    if ( n == 1 ){
        printf("1\n");
        return 0;
    }

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            if ( diff < 0 ) {
                printf("-1\n");
                return 0;
            }
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%ld\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include<stdio.h>

int main() {
    int n;
    int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    long sums[1002];
    long diff;
    char flag = 1;

    scanf("%d", &n);

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%ld\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include<stdio.h>

int main() {
    int n;
    unsigned int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    unsigned long long sums[1002];
    unsigned long long diff;
    char flag = 1;

    scanf("%d", &n);
    if ( n == 1 ){
        printf("1\n");
        return 0;
    }

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            if ( diff <= 0 || diff > 1e+18 ) {
                printf("-1\n");
                return 0;
            }
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%I64u\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include<stdio.h>

int main() {
    int n;
    unsigned int input[500][500];
    int x,y;
    int blank_x,blank_y;
    int i;
    unsigned long long sums[1002];
    unsigned long long diff;
    char flag = 1;

    scanf("%d", &n);
    if ( n == 1 ){
        printf("1\n");
        return 0;
    }

    sums[1000] = 0;
    sums[1001] = 0;
    for ( i = 0; i < n; i++ ) {
        sums[i] = 0;
        sums[500+i] = 0;
    }

    for ( y = 0; y < n; y++ ) {
        for ( x = 0; x < n; x++ ) {
            scanf("%d", &input[x][y]);
            if ( input[x][y] == 0 ) {
                blank_x = x;
                blank_y = y;
            }
            sums[x] += input[x][y];
            sums[500+y] += input[x][y];
            if ( x == y ) sums[1000] += input[x][y];
            if ( x == (n-y-1) ) sums[1001] += input[x][y];
        }
    }

    for ( i = 0; i < n; i++ ) {
        if ( i != blank_x ) {
            diff = sums[i] - sums[blank_x];
            if ( diff <= 0 ) {
                printf("-1\n");
                return 0;
            }
            sums[blank_x] += diff;
            sums[500+blank_y] += diff;
            if ( blank_x == blank_y ) sums[1000] += diff;
            if ( blank_x == (n-blank_y-1) ) sums[1001] += diff;
            break;
        }
    }

    if ( sums[0] != sums[1000] || sums[0] != sums[1001] )
        flag = 0;
    else {
        for ( i = 0; i < n; i++ ) {
            if ( sums[0] != sums[i] || sums[0] != sums[500+i] ) {
                flag = 0;
                break;
            }
        }
    }

    if ( flag ) {
        printf("%I64d\n", diff);
    } else {
        printf("-1\n");
    }

    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int L[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void read ( int &x ) {
    char c ;
    while ( ( c = getchar () ) < '0' || c > '9' ) ;
    x = c - '0' ;
    while ( ( c = getchar () ) >= '0' && c <= '9' )
        x = x * 10 + c - '0' ;
}

void solve () {
    int ch , x , y , u , v ;
    cntE = 1 ;
    //CLR ( H , 0 ) ;
    //CLR ( p , 0 ) ;
    //CLR ( L , 0 ) ;
    REP ( i , 0 , m ) {
        read ( u ) , read ( v ) ;
        x = find ( u ) ;
        y = find ( v ) ;
        if ( x != y ) {
            p[x] = y ;
            addedge ( u , v ) ;
        }
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = -1 ;
            dfs ( i ) ;
            length = -1 ;
            dfs ( X ) ;
            L[i] = length ;
        }
    REP ( i , 0 , q ) {
        read ( ch ) , read ( x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , L[find ( x )] ) ;
        else {
            read ( y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                L[y] = max ( max ( L[x] , L[y] ) , ( L[x] + 1 ) / 2 + ( L[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int len[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y ;
    cntE = 0 ;
    CLR ( H , 0 ) ;
    CLR ( p , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &x , &y ) ;
        x = find ( x ) ;
        y = find ( y ) ;
        if ( x != y )
            p[x] = y ;
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = 0 ;
            dfs ( i ) ;
            length = 0 ;
            dfs ( X ) ;
            len[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , len[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                len[y] = max ( max ( len[x] , len[y] ) , ( len[x] + 1 ) / 2 + ( len[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int len[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y ;
    cntE = 1 ;
    CLR ( H , 0 ) ;
    CLR ( p , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &x , &y ) ;
        x = find ( x ) ;
        y = find ( y ) ;
        if ( x != y ) {
            p[x] = y ;
            addedge ( x , y ) ;
        }
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = 0 ;
            dfs ( i ) ;
            length = 0 ;
            dfs ( X ) ;
            len[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , len[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                len[y] = max ( max ( len[x] , len[y] ) , ( len[x] + 1 ) / 2 + ( len[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int L[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y , u , v ;
    cntE = 1 ;
    //CLR ( H , 0 ) ;
    //CLR ( p , 0 ) ;
    //CLR ( L , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &u , &v ) ;
        x = find ( u ) ;
        y = find ( v ) ;
        if ( x != y ) {
            p[x] = y ;
            addedge ( u , v ) ;
        }
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = -1 ;
            dfs ( i ) ;
            length = -1 ;
            dfs ( X ) ;
            L[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , L[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                L[y] = max ( max ( L[x] , L[y] ) , ( L[x] + 1 ) / 2 + ( L[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int deepth[MAXN] ;
int X , length ;
int len[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    deepth[u] = d ;
    if ( length < d ) {
        d = length ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y ;
    cntE = 0 ;
    CLR ( H , 0 ) ;
    CLR ( p , 0 ) ;
    CLR ( deepth , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &x , &y ) ;
        x = find ( x ) ;
        y = find ( y ) ;
        if ( x != y )
            p[x] = y ;
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = 0 ;
            dfs ( i ) ;
            length = 0 ;
            dfs ( X ) ;
            len[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , len[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                len[y] = max ( max ( len[x] , len[y] ) , ( len[x] + 1 ) / 2 + ( len[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 3005 ;
const int MAXE = 6005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int len[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y ;
    cntE = 1 ;
    CLR ( H , 0 ) ;
    CLR ( p , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &x , &y ) ;
        x = find ( x ) ;
        y = find ( y ) ;
        if ( x != y ) {
            p[x] = y ;
            addedge ( x , y ) ;
        }
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = 0 ;
            dfs ( i ) ;
            length = 0 ;
            dfs ( X ) ;
            len[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , len[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                len[y] = max ( max ( len[x] , len[y] ) , ( len[x] + 1 ) / 2 + ( len[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 300005 ;
const int MAXE = 600005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} E[MAXE] ;

int H[MAXN] , cntE ;
int p[MAXN] ;
int X , length ;
int L[MAXN] ;
int n , m , q ;

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

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
    E[cntE] = Edge ( u , H[v] ) ;
    H[v] = cntE ++ ;
}

void dfs ( int u , int fa = -1 , int d = 0 ) {
    if ( length < d ) {
        length = d ;
        X = u ;
    }
    for ( int i = H[u] ; i ; i = E[i].n )
        if ( E[i].v != fa )
            dfs ( E[i].v , u , d + 1 ) ;
}

void solve () {
    int ch , x , y , u , v ;
    cntE = 1 ;
    CLR ( H , 0 ) ;
    CLR ( p , 0 ) ;
    CLR ( L , 0 ) ;
    REP ( i , 0 , m ) {
        scanf ( "%d%d" , &u , &v ) ;
        x = find ( u ) ;
        y = find ( v ) ;
        if ( x != y ) {
            p[x] = y ;
            addedge ( u , v ) ;
        }
    }
    FOR ( i , 1 , n )
        if ( !p[i] ) {
            length = -1 ;
            dfs ( i ) ;
            length = -1 ;
            dfs ( X ) ;
            L[i] = length ;
        }
    REP ( i , 0 , q ) {
        scanf ( "%d%d" , &ch , &x ) ;
        if ( ch == 1 )
            printf ( "%d\n" , L[find ( x )] ) ;
        else {
            scanf ( "%d" , &y ) ;
            x = find ( x ) ;
            y = find ( y ) ;
            if ( x != y ) {
                p[x] = y ;
                L[y] = max ( max ( L[x] , L[y] ) , ( L[x] + 1 ) / 2 + ( L[y] + 1 ) / 2 + 1 ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%d" , &n , &m , &q ) )
        solve () ;
    return 0 ;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], Dist[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline int BFS ( int Start )
{
    queue < int > Q;
    queue < int > All;

    Q.push ( Start );
    while ( ! Q.empty ( ) )
    {
        int Curr = Q.front ( );
        Visited[Curr] = true;
        All.push ( Curr );
        Q.pop ( );
        for ( vector < int > :: iterator it = E[Curr].begin ( ); it != E[Curr].end ( ); it++ )
        {
            int Next = * it;
            if ( Dist[Next] ) continue;
            Dist[Next] = Dist[Curr] + 1;
            Q.push ( Next );
        }
    }

    int idxMax = -1;
    for ( int i = 0; i < N; i++ ) if ( ( idxMax == -1 ) || ( Dist[i] > Dist[idxMax] ) ) idxMax = i;

    while ( ! All.empty ( ) )
    {
        Dist[All.front ( )] = 0;
        All.pop ( );
    }

    return idxMax;
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        idx = FindRoot ( idx );
        idy = FindRoot ( idy );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        LongestPath[FindRoot ( i )] = BFS ( BFS ( i ) );
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline void Find ( int Curr, int Prev, int Dist )
{
    Visited[Curr] = true;
    if ( Dist > Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        idx = FindRoot ( idx );
        idy = FindRoot ( idy );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        Best = -1;
        Find ( i, 0, 0 );
        Best = -1;
        Find ( idxBest, 0, 0 );
        LongestPath[FindRoot ( i )] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], Dist[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline pii BFS ( int Start )
{
    queue < int > Q;
    queue < int > All;

    Q.push ( Start );
    while ( ! Q.empty ( ) )
    {
        int Curr = Q.front ( );
        Visited[Curr] = true;
        All.push ( Curr );
        Q.pop ( );
        for ( vector < int > :: iterator it = E[Curr].begin ( ); it != E[Curr].end ( ); it++ )
        {
            int Next = * it;
            if ( Dist[Next] ) continue;
            Dist[Next] = Dist[Curr] + 1;
            Q.push ( Next );
        }
    }

    int idxMax = -1;
    for ( int i = 0; i < N; i++ ) if ( ( idxMax == -1 ) || ( Dist[i] > Dist[idxMax] ) ) idxMax = i;
    int maxDist = Dist[idxMax];

    while ( ! All.empty ( ) )
    {
        Dist[All.front ( )] = 0;
        All.pop ( );
    }

    return make_pair ( idxMax, maxDist );
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        idx = FindRoot ( idx );
        idy = FindRoot ( idy );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        LongestPath[FindRoot ( i )] = BFS ( BFS ( i ).first ).second;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline void Find ( int Curr, int Prev, int Dist )
{
    Visited[Curr] = true;
    if ( Dist >= Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        Best = -1;
        Find ( i, 0, 0 );
        Best = -1;
        Find ( idxBest, 0, 0 );
        LongestPath[FindRoot ( i )] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 3 * 100 * 1000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

int Find ( int Curr, int Prev, int Dist )
{
    if ( Dist > Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    Visited[Curr] = true;
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        idxBest = -1;
        Best = 0;
        Find ( i, 0, 0 );
        idxBest = -1;
        Best = 0;
        Find ( idxBest, 0, 0 );
        LongestPath[Root[i]] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

int Find ( int Curr, int Prev, int Dist )
{
    if ( Dist > Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    Visited[Curr] = true;
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        idxBest = -1;
        Best = 0;
        Find ( i, 0, 0 );
        idxBest = -1;
        Best = 0;
        Find ( idxBest, 0, 0 );
        LongestPath[Root[i]] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline void Find ( int Curr, int Prev, int Dist )
{
    Visited[Curr] = true;
    if ( Dist >= Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        idx = FindRoot ( idx );
        idy = FindRoot ( idy );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        Best = -1;
        Find ( i, 0, 0 );
        Best = -1;
        Find ( idxBest, 0, 0 );
        LongestPath[FindRoot ( i )] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
    Aleksandar "Al3kSaNdaR" Ivanović
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <bitset>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <utility>
#include <functional>

#define pb push_back
#define mp make_pair
#define sz size
#define all(X) (X).begin(), (X).end ()
#define for_each(it, X) for (__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)

using namespace std;

typedef long long int lld;
typedef pair < int, int > pii;

const int MaxN = 300000 + 5;

int N, M, Q, Best, idxBest, Root[MaxN], LongestPath[MaxN];
bool Visited[MaxN];
vector < int > E[MaxN];

int FindRoot ( int idx )
{
    if ( Root[idx] == idx ) return idx;
    else return Root[idx] = FindRoot ( Root[idx] );
}

inline void Find ( int Curr, int Prev, int Dist )
{
    Visited[Curr] = true;
    if ( Dist > Best )
    {
        Best = Dist;
        idxBest = Curr;
    }
    for_each ( it, E[Curr] )
    {
        int Next = * it;
        if ( Next == Prev ) continue;
        Find ( Next, Curr, Dist + 1 );
    }
}

int main ( void )
{
    cin.sync_with_stdio ( 0 );
    cout.sync_with_stdio ( 0 );

    cin >> N >> M >> Q;
    for ( int i = 0; i < N; i++ ) Root[i] = i;

    for ( int i = 0; i < M; i++ )
    {
        int idx, idy;
        cin >> idx >> idy;
        idx--;
        idy--;
        E[idx].pb ( idy );
        E[idy].pb ( idx );
        idx = FindRoot ( idx );
        idy = FindRoot ( idy );
        if ( idx == idy ) continue;
        Root[idx] = idy;
    }

    for ( int i = 0; i < N; i++ )
    {
        if ( Visited[i] ) continue;
        Best = -1;
        Find ( i, -1, 0 );
        Best = -1;
        Find ( idxBest, -1, 0 );
        LongestPath[FindRoot ( i )] = Best;
    }

    for ( int i = 0; i < Q; i++ )
    {
        int TypeOfQuery;
        cin >> TypeOfQuery;

        if ( TypeOfQuery == 1 )
        {
            int idx;
            cin >> idx;
            idx--;
            idx = FindRoot ( idx );
            cout << LongestPath[idx] << endl;
        }
        else
        {
            int idx, idy;
            cin >> idx >> idy;
            idx--;
            idy--;
            idx = FindRoot ( idx );
            idy = FindRoot ( idy );
            if ( idx == idy ) continue;

            int leftPath = LongestPath[idx], rightPath = LongestPath[idy];
            Root[idx] = idy;
            int Path = max ( leftPath, rightPath );
            Path = max ( Path, ( ( leftPath + 1 ) / 2 + ( rightPath + 1 ) / 2 ) + 1 );
            LongestPath[idy] = Path;
        }
    }

    return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN],st[MAXN]={},l[MAXN]={},dep[MAXN],mdep;
int ds[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

void dfs(int x,int f,int k){
	st[x]=k;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,k);
	}
	if(dep[x]>dep[mdep]) mdep=x;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++){
		if(st[i]>0) continue;
		dep[i]=0;
		dfs(i,-1,++k);
		dfs(mdep,-1,k);
		l[k]=dep[mdep];
		ds[k]=k;
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp= l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]+1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN]={},l[MAXN]={},dep[MAXN],mdep=0;
int ds[MAXN];
bool vis[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

void dfs(int x,int f,int r){
	vis[x]=1;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,r);
	}
	if(dep[x]>dep[mdep]) mdep=x;
	uni(x,r);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	memset(vis,0,sizeof(vis));
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	for(int i=1;i<=n;i++) ds[i]=i;
	for(int i=1;i<=n;i++){
		if(vis[i]) continue;
		dep[i]=0;
		mdep=i;
		dep[mdep]=0;
		dfs(i,-1,i);
		dep[mdep]=0;
		dfs(mdep,-1,i);
		l[find(i)]=dep[mdep];
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			if(find(x)==find(y)) continue;
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp=l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]%2==0?l[find(y)]/2 : l[find(y)] /2 +1;
			tmp+=1;
			l[find(x)]=max(l[find(x)],tmp);
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN],st[MAXN]={},l[MAXN]={},dep[MAXN],mdep;
int ds[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

void dfs(int x,int f,int k){
	st[x]=k;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,k);
	}
	if(dep[x]>dep[mdep]) mdep=x;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++){
		if(st[i]>0) continue;
		dep[i]=0;
		dfs(i,-1,++k);
		dep[mdep]=0;
		dfs(mdep,-1,k);
		l[k]=dep[mdep];
		ds[k]=k;
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			x=st[x];
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			x=st[x];y=st[y];
			if(find(x)==find(y)) continue;
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp= l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]+1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN]={},l[MAXN]={},dep[MAXN],mdep=0;
int ds[MAXN];
bool vis[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

void dfs(int x,int f,int r){
	vis[x]=1;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,r);
	}
	if(dep[x]>dep[mdep]) mdep=x;
	uni(x,r);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	memset(vis,0,sizeof(vis));
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++) ds[i]=i;
	for(int i=1;i<=n;i++){
		if(vis[i]) continue;
		dep[i]=0;
		mdep=i;
		dep[mdep]=0;
		dfs(i,-1,i);
		dep[mdep]=0;
		dfs(mdep,-1,i);
		l[i]=dep[mdep];
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			if(find(x)==find(y)) continue;
			int tmp=l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]%2==0?l[find(y)]/2 : l[find(y)] /2 +1;
			tmp+=1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN]={},st[MAXN]={},l[MAXN]={},dep[MAXN],mdep=0;
int ds[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

void dfs(int x,int f,int k){
	st[x]=k;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,k);
	}
	if(dep[x]>dep[mdep]) mdep=x;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	dep[0]=-1;
	for(int i=1;i<=n;i++){
		if(st[i]>0) continue;
		dep[i]=0;
		mdep=0;
		dfs(i,-1,++k);
		dep[mdep]=0;
		dfs(mdep,-1,k);
		l[k]=dep[mdep];
		ds[k]=k;
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			x=st[x];
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			x=st[x];y=st[y];
			if(find(x)==find(y)) continue;
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp= l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]+1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN]={},l[MAXN]={},dep[MAXN],mdep=0;
int ds[MAXN];
bool vis[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

void dfs(int x,int f,int r){
	vis[x]=1;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,r);
	}
	if(dep[x]>dep[mdep]) mdep=x;
	uni(x,r);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++) ds[i]=i;
	for(int i=1;i<=n;i++){
		if(vis[i]) continue;
		dep[i]=0;
		mdep=i;
		dep[mdep]=0;
		dfs(i,-1,i);
		dep[mdep]=0;
		dfs(mdep,-1,i);
		l[i]=dep[mdep];
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			if(find(x)==find(y)) continue;
			int tmp=l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]%2==0?l[find(y)]/2 : l[find(y)] /2 +1;
			tmp+=1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN]={},st[MAXN]={},l[MAXN]={},dep[MAXN],mdep=0;
int ds[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

void dfs(int x,int f,int k){
	st[x]=k;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,k);
	}
	if(dep[x]>dep[mdep]) mdep=x;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++){
		if(st[i]>0) continue;
		dep[i]=0;
		mdep=0;
		dep[mdep]=0;
		dfs(i,-1,++k);
		dep[mdep]=0;
		dfs(mdep,-1,k);
		l[k]=dep[mdep];
		ds[k]=k;
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			x=st[x];
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			x=st[x];y=st[y];
			if(find(x)==find(y)) continue;
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp= l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]%2==0?l[find(y)]/2 : l[find(y)] /2 +1;
			tmp+=1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	return 0;
}


/*
 * cf445c.cpp
 * Copyright (C) 2014 Chen Ran <crccw@moonux.org>
 *
 * Distributed under terms of the MIT license.
 */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 300100

using namespace std;
typedef long long LL;

struct Edge{
	int t,next;
}e[2*MAXN];

int ek=0;
int n,m,q;

int first[MAXN],st[MAXN]={},l[MAXN]={},dep[MAXN],mdep;
int ds[MAXN];

void addEdge(int a,int b){
	e[++ek].t=a;e[ek].next=first[b];first[b]=ek;
	e[++ek].t=b;e[ek].next=first[a];first[a]=ek;
}

void dfs(int x,int f,int k){
	st[x]=k;
	for(int it=first[x];it>0;it=e[it].next){
		int u=e[it].t;
		if(u==f) continue;
		dep[u]=dep[x]+1;
		dfs(u,x,k);
	}
	if(dep[x]>dep[mdep]) mdep=x;
}

int find(int x){
	if(ds[x]==x) return x;
	int tmp=find(ds[x]);
	return ds[x]=tmp;
}

void uni(int f,int t){
	ds[find(f)]=find(t);
}

int main(int argc, const char *argv[])
{
	int a,b,op,x,y;
	int k;
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		addEdge(a,b);
	}
	k=0;
	for(int i=1;i<=n;i++){
		if(st[i]>0) continue;
		dep[i]=0;
		dfs(i,-1,++k);
		dep[mdep]=0;
		dfs(mdep,-1,k);
		l[k]=dep[mdep];
		ds[k]=k;
	}
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			x=st[x];
			printf("%d\n",l[find(x)]);
		}else{
			scanf("%d%d",&x,&y);
			x=st[x];y=st[y];
			if(l[find(x)]<l[find(y)]) swap(x,y);
			int tmp= l[find(x)]%2==0?l[find(x)]/2 : l[find(x)] /2 +1;
			tmp+=l[find(y)]+1;
			l[find(x)]=tmp;
			uni(y,x);
		}
	}

	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;

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

int find_root(int u){

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

}

void add(int u,int v){

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

	if(uu==vv) return;

	if(sz[uu]>sz[vv]){

		sz[uu]+=sz[vv];

		root[vv]=uu;

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

	}

	else{

		sz[vv]+=sz[uu];

		root[uu]=vv;

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

	}

}

void solve_C(){

	int n,m,q,u,v;

	gn(n,m,q);

	for(int i=1; i<=n; i++) root[i]=i,sz[i]=1;

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

		gn(u,v);add(u,v);

	}

	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 <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 301010

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

int dfs(int u, int id, int &d) {

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

	int mx[2]={0, };

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

		int v=adj[u][i];

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

		smax(mx[1], dfs(v, id, d)+1);

		if (mx[1]>mx[0]) swap(mx[0], mx[1]);

	}

	smax(d, mx[0]+mx[1]);

	return mx[0];

}

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;

		dfs(i, i, d[i]);

	}

	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;

}

#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];

int dfs(int u, int id, int &d) {

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

	int mx[2]={0, };

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

		int v=adj[u][i];

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

		smax(mx[1], dfs(v, id, d)+1);

		if (mx[1]>mx[0]) swap(mx[0], mx[1]);

	}

	smax(d, mx[0]+mx[1]);

	return mx[0];

}

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;

		dfs(i, i, d[i]);

	}

	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 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 root) {

	vst[u]=1;

	::root[u]=root;

	int one=0, two=0;

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

		int v=adj[u][i];

		if(!vst[v]) {

			dfs(v, root);

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

				two=one;

				one=mx[v]+1;

			}

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

		}

	}

	smax(d[root], 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]) {

		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 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 root) {

	vst[u]=1;

	::root[u]=root;

	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[root], 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]) {

		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 bpt(x) (__builtin_popcount(x))

#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 bit(x, y) (((x)>>(y))&1)

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<class T, class U> inline void smin(T &a, U b) {if (a>b) a=b;}

template<class T, class 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!='-' && c!=-1);if (c==-1) return ;if (c=='-') sg=1,c=getchar(); for (x=0; c>='0' && c<='9'; x=(x<<1)+(x<<3)+c-'0', c=getchar());if (sg) x=-x;}

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

template<class U, class V>inline void gn(U &u, V &v){gn(u);gn(v);}

template<class U, class V, class W>inline void gn(U &u, V &v, W &w){gn(u); gn(v, w);}

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

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

template<class U, class V> inline void print(U u, V v) {printsp(u);println(v);}

template<class U, class V, class W> inline void print(U u, V v, W w){printsp(u);print(v, w);}

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

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

	return ans;

}

#define NN 330303

#define x first

#define y second

VI adj[NN];

int root[NN],sz[NN],D[NN],vst[NN];

int tmp;

int find(int x){

	while(x!=root[x]) x=root[x];

	return x;

}

bool same(int a,int b){

	return 	find(a)==find(b);

}

void unite(int a,int b){

	a=find(a);

	b=find(b);

	if(a==b) return ;

	if(sz[a]<sz[b]) swap(a,b);

	sz[a]+=sz[b];

	root[b]=a;

	D[a]=max(D[a],max(D[b],(D[a]+1)/2+(D[b]+1)/2+1));

}

int dfs(int u){

	vst[u]=1;

	int mx[2]={0, };

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

		int v=adj[u][i];

		if(vst[v]) continue;

		smax(mx[1], dfs(v)+1);

		if(mx[0]<mx[1]) swap(mx[0], mx[1]);

	}

	smax(tmp, mx[0]+mx[1]);

	return mx[0];

}

int main() {

#ifndef ONLINE_JUDGE

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

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

#endif

	int n,m,q;

	gn(n,m,q);

	int u,v;

	for(int i=1;i<=n;i++) root[i]=i,sz[i]=1;

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

		gn(u,v);

		adj[u].push_back(v);

		adj[v].push_back(u);

		unite(u,v);

	}

	for(int i=1;i<=n;i++){

		if(!vst[i]){

			tmp=0;

			dfs(i);

			D[find(i)]=tmp;

		}

	}

	int x,y;

	while(q--){

		int tp;

		gn(tp);

		if(tp==1){

			gn(x);

			x=find(x);

			println(D[x]);

		}

		else{

			gn(x,y);

			unite(x,y);

		}

	}

	return 0;

}


#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 v) {

	vst[u]=1;

	int one=0, two=0;

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

		int v=adj[u][i];

		if(v!=u) {

			root[v]=u;

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

			}

		}

	}

}