Problem: Consider a string with rings on both ends. Rings have positive integers to distinguish them. Rings on both ends of the string have different numbers a and b. Describe this as [a, b]. If there are multiple strings and the number attached to the ring of one string and the other string is the same, these strings can be connected at that ring, and the one made by connecting is called a chain. For example, the strings [1, 3] and [3, 4] form the chain [1, 3, 4]. The string and the chain or the chains are also connected at the ring with the same integer. Suppose you can.

For example, a chain [1, 3, 4] and a string [5, 1] ​​can form [5, 1, 3, 4], and a chain [1, 3, 4] and a chain [2, 3, 5] can form [5, 1, 3, 4]. The chain [1, 3, 4] and the chain [4, 6, 1] form a ring.

There are various shapes like this, but in some of them, rings with the same number follow only once. Multiple connected strings are called chains. For example, chains [1, 3, 4] The centrally crossed shape of the chains [2, 3, 5] also includes the chains [1, 3, 5], [2, 3, 4], and the chains [1, 3, 4]. And chains [4, 6, 1] loops include chains such as [1, 3, 4, 6], [3, 4, 6, 1], [4, 6, 1, 3]. ..

For these chains, the number contained is defined as the length. For a given number of strings, anything that can be connected can form a shape that contains one or more chains. Create a program to find the length of the chain.

The first line of the input data contains the number of strings, the positive integer 1 ≤ n ≤ 100, and each of the following n lines contains two integers a, b separated by blanks 1 ≤ a <b ≤ 100. The two integers in each line represent the integers at both ends of one string.

Input example 1 | Input example 2 | Input example 3
--- | --- | ---
|
7 | 6 | 7
1 3 | 1 2 | 1 3
3 4 | 2 3 | 2 4
1 4 | 3 4 | 3 5
2 7 | 4 5 | 4 6
5 7 | 1 5 | 6 7
6 7 | 2 6 | 2 6
1 7 | | 4 7
Output example 1 | Output example 2 | Output example 3
5 | 6 | 4

input

The input consists of multiple datasets. Input ends when n is 0. The number of datasets does not exceed 10.

output

For each dataset, the maximum chain length is output on one line.





Example

Input

7
1 3
3 4
1 4
2 7
5 7
6 7
1 7
6
1 2
2 3
3 4
4 5
1 5
2 6
7
1 3
2 4
3 5
4 6
6 7
2 6
4 7
0


Output

5
6
4

Solution (in CPP):

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

#define MAX 110

using namespace std;

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

class State{
public:
  int pos;
  State(int pos):pos(pos){
    len = 1;
  }
  int len;
  bool vis[MAX];
};

int BFS(int st, const vector<Node> &G){
  int ret = 1;
  queue<State> q;
  State init(st);

  fill(init.vis,init.vis+MAX,false);
  init.vis[st]=true;
  q.push(init);

  while(!q.empty()){
    bool NG=false;
    State now = q.front();
    q.pop();

    ret = max( ret, now.len );

    const set<int> &S = G[now.pos].con;
    for(set<int>::iterator its = S.begin();
	its != S.end();
	++its){
      int nx = *its;
      if( !now.vis[ nx ] ){
	State next = now;
	next.pos = nx;
	next.vis[nx] = true;
	next.len++;
	q.push( next );
      }
    }
  }
  return ret;
}

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;
    //if( !vis[nx] ){
      bans=max(bans,now+1);
      //vis[nx]=true;
      ret=max(ret,Backtrack(nx,now+1,bans,vis,memo,G) );
      //vis[nx]=false;
      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,};
	//vis[st]=true;
	int btret = Backtrack( st, 0, ans, vis, memo, G );
	memo[st]=btret;
	ans=max(ans,btret);
      }
    }
    cout << ans << endl;
  }
  return 0;
}