#include<iostream>
#include<set>
#include<algorithm>
#include<list>
#include<queue>

#define MAX 110

using namespace std;

class Node{
public:
  set<int> con;
};

typedef vector<Node> graph;
typedef list< vector<int> > forest;

void MakeForest(const graph &g, bool exist[MAX], forest &f){
  bool vis[MAX]={false};
  for(int x=0;x<MAX;++x){
    if(!vis[x]&&exist[x]){
      queue<int> q;
      bool tvis[MAX]={false};
      q.push(x);
      tvis[x]=true;
      while(!q.empty()){
	int now=q.front();q.pop();const set<int> &C=g[now].con;
	for(set<int>::iterator its=C.begin();its!=C.end();++its){
	  if(!tvis[*its]){tvis[*its]=true;q.push(*its);}
	}
      }
      vector<int> tmp;
      f.push_back( tmp );
      for(int i=0;i<MAX;++i){
	if(tvis[i]){
	  vis[i]=true;
	  f.back().push_back( i );
	}
      }
    }
  }
}

int Backtrack(int pos, int now, int &bans, bool vis[], int memo[], const graph &G){
  const set<int> &C = G[pos].con;
  int ret = now;
  if(vis[pos]){return now;}
  vis[pos]=true;
  if(now+memo[pos]<=bans)return bans;
  for(set<int>::iterator itc=C.begin();itc!=C.end();++itc){
    int nx = *itc;
    bans=max(bans,now+1);
    ret=max(ret,Backtrack(nx,now+1,bans,vis,memo,G) );
    bans=max(bans,ret);
  }
  vis[pos]=false;
  return ret;
}

int main()
{
  while(true){
    int ans = 2;
    int n;
    cin >> n;
    if( n == 0 )break;
    graph G(MAX);
    forest F;
    bool exist[MAX]={false,};
    for(int i = 0;  i < n ; ++i){
      int a,b;
      cin >> a >> b;
      exist[a]=exist[b]=true;
      G[a].con.insert(b);
      G[b].con.insert(a);
    }

    MakeForest(G,exist,F);

    int memo[MAX];
    for(int i=0;i<MAX;++i){
      memo[i]=MAX*MAX;
    }
    for(forest::iterator itf=F.begin();itf!=F.end();++itf){
      if((*itf).size()<=ans)continue;
      for(int i = 0; i < (*itf).size(); ++i){
	int st=(*itf)[i];
	bool vis[MAX]={false,};
	int btret = Backtrack( st, 0, ans, vis, memo, G );
	memo[st]=btret;
	ans=max(ans,btret);
      }
    }
    cout << ans << endl;
  }
  return 0;
}