// Original C++ solution (slower):
#include <vector>

#include <iostream>

#include <algorithm>



using namespace std;



vector<vector<int> > G;



vector<bool> used;



int rec(int pos)

{

    used[pos] = true; int ret = 1;

    

    for(int i = 0; i < G[pos].size(); i++)

    {

        if(!used[G[pos][i]])

        {

            ret = max(ret, rec(G[pos][i]) + 1);

        }

    }

    

    used[pos] = false;

    

    return ret;

}



int main()

{

    int N, A, B;

    

    while(true)

    {

        scanf("%d", &N);

        

        if(N == 0) { break; }



        G = vector<vector<int> >(100, vector<int>());

        

        used = vector<bool>(100);

    

        for(int i = 0; i < N; i++)

        {

            scanf("%d", &A); A--;

            scanf("%d", &B); B--;

        

            G[A].push_back(B);

            G[B].push_back(A);

        }

        

        int nodes = 0;

        

        for(int i = 0; i < 100; i++)

        {

            if(G[i].size())

            {

                nodes++;

            }

        }

    

        int ret = 0;

    

        for(int i = 0; i < 100; i++)

        {

            if(G[i].size())

            {

                ret = max(ret, rec(i));

                

                if(ret == nodes) { break; }

            }

        }

        

        printf("%d\n", ret);

    }

    

    return 0;

}

// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <algorithm>

#pragma warning(disable : 4996)

using namespace std;

int N, A, B, v[100], r[100], G[100][199];

int rec(int pos) {

	int ret = 0; v[pos] = 1;

	for (int i = 0; i < r[pos]; i++) {

		if (!v[G[pos][i]]) ret = max(ret, rec(G[pos][i]));

	}

	v[pos] = 0;

	return ret + 1;

}

int main() {

	while (scanf("%d", &N), N) {

		for (int i = 0; i < 100; i++) r[i] = 0;

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

			scanf("%d%d", &A, &B), A--, B--;

			G[A][r[A]++] = B, G[B][r[B]++] = A;

		}

		int ret = 0;

		for (int i = 0; i < 100; i++) ret = max(ret, rec(i));

		printf("%d\n", ret);

	}

	return 0;

}

// Fastest known solution for this problem:
#include <iostream>

#include <set>

#include <cstring>

#include <vector>

using namespace std;



//int node[101][101];

int visit[101];

int ans,last;

int die[101];

int flag;



void dfs(int now, int cnt, int *st, vector<vector<int> >& vv){

	if( cnt>ans ){

		ans=cnt;

		last = now;

		flag = 1;

	}

	for(int next=0; next<vv[now].size(); next++)if( !visit[vv[now][next]] ){

		int k = vv[now][next];

		visit[k] = die[k] = 1;

		st[cnt] = k;

		dfs(k,cnt+1,st,vv);

		visit[k] = 0;

	}

	return ;

}



int main(){

	int n;

	while(cin>>n,n){

		set<int> s;

		vector<vector<int> > vv(101);

		ans = 0;

		//memset(node,0,sizeof(node));

		memset(visit,0,sizeof(visit));

		memset(die,0,sizeof(die));

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

			int a,b; cin>>a>>b;

			//node[a][b] = node[b][a] = 1;

			vv[a].push_back(b);

			vv[b].push_back(a);

			s.insert(a);

			s.insert(b);

		}

		int tmp[101];

		/*

		for(int i=0; i<vv.size(); i++){

			printf("vv[%d].size = %d\n",i,vv[i].size());

			for(int j=0; j<vv[i].size(); j++)

				printf("%d ",vv[i][j]);

			puts("");

		}

		*/

		for(set<int>::iterator it=s.begin(); it!=s.end(); it++)if( !die[*it] ){

			flag = 0;

			

			visit[*it]=1;

			tmp[0] = *it;

			dfs(*it,1,tmp,vv);

			visit[*it]=0;

			

			die[last] = 0;

			//printf("*it:%d\n",*it);



		}

		printf("%d\n",ans);

	}

	return 0;

}