#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<algorithm>
#include<climits>
using namespace std;
ifstream in("darb.in");
ofstream out("darb.out");
class graf{
protected:
int NrMuchii, NrNoduri;
bool eOrientat;
vector<vector<int>> adiacenta;
public:
graf(int NrNod = 0, int NrMuc = 0, bool orientat = false, vector<vector<int>> vecAdiacenta = {}){
this->NrNoduri = NrNod;
this->NrMuchii = NrMuc;
this->eOrientat = orientat;
this->adiacenta = vecAdiacenta;
}
~graf(){
this->NrNoduri = 0;
this->NrMuchii = 0;
}
void setNrNoduri(int&);
void setNrMuchii(int&);
void setMuchii(int, int);
int getNrNoduri();
int getNrMuchii();
void citireMuchii();
vector<int> BFS(int, vector<int> &);
void DFS(int, bool[]);
int NrComponenteConexe(bool[]);
int gaseste(int, vector<int> &);
void uneste(int, int, vector<int> &);
vector<int> disjoint(vector<pair<int, pair<int, int>>>);
int diamArb();
};
class grafCuCost : public graf
{
private:
vector<vector<pair<pair<int, int>, int>>> costuriVecini;
public:
grafCuCost(int NrNoduri = 0, int NrMuchii = 0, bool orientat = false, vector<vector<int>> adiacenta = {}) : graf(NrNoduri, NrMuchii, orientat, adiacenta){}
void setMuchiiCost(int, int, int);
vector<int> apm(int, int &);
vector<int> Bellman_Ford(int);
vector<int> Dijkstra(int);
vector<vector<pair<pair<int, int>, int>>> RoyFloyd();
};
void grafCuCost::setMuchiiCost(int n1, int n2, int cost){
pair<pair<int, int>, int> muchieCost;
costuriVecini.resize(this->NrNoduri + 1);
muchieCost = make_pair(make_pair(n1, n2), cost);
costuriVecini[n1].push_back(muchieCost);
if(this->eOrientat == false){
muchieCost.first.second = n1;
costuriVecini[n2].push_back(muchieCost);
}
}
void graf::setNrNoduri(int &n){
NrNoduri = n;
}
void graf::setNrMuchii(int &m){
NrMuchii = m;
}
void graf::setMuchii(int nod1, int nod2){
adiacenta.resize(NrNoduri + 1);
adiacenta[nod1].push_back(nod2);
if(!eOrientat){
adiacenta[nod2].push_back(nod1);
}
}
int graf::getNrNoduri(){
return NrNoduri;
}
int graf::getNrMuchii(){
return NrMuchii;
}
void graf::citireMuchii(){
int n1, n2;
adiacenta.resize(NrNoduri + 1);
for(int i = 0; i < NrMuchii; i++){
in>>n1>>n2;
setMuchii(n1, n2);
if(!eOrientat){
setMuchii(n2, n1);
}
}
}
vector<int> graf::BFS(int NodSursa, vector<int> &vizitat){
vector<int> distanta(NrNoduri + 1, 0);
queue<int> coada;
coada.push(NodSursa);
vizitat[NodSursa] = 1;
while(!coada.empty()){
for(int nod : adiacenta[coada.front()]){
if(!vizitat[nod]){
vizitat[nod] = 1;
coada.push(nod);
distanta[nod] = distanta[coada.front()] + 1;
}
}
coada.pop();
}
return distanta;
}
void graf::DFS(int Nod, bool vizitat[]){
vizitat[Nod] = true;
for(int vecin : adiacenta[Nod]){
if(!vizitat[vecin]){
DFS(vecin, vizitat);
}
}
}
int graf::NrComponenteConexe(bool vizitat[]){
int NrCompCon = 0;
for(int Nod = 1; Nod <= NrNoduri; Nod++){
if(!vizitat[Nod]){
NrCompCon++;
DFS(Nod, vizitat);
}
}
return NrCompCon;
}
int graf::gaseste(int nod, vector<int> &radacina){
if(radacina[nod] != nod){
radacina[nod] = gaseste(radacina[nod], radacina);
}
return radacina[nod];
}
void graf::uneste(int x, int y, vector<int> &radacina){
int rad1, rad2;
rad1 = gaseste(x, radacina);
rad2 = gaseste(y, radacina);
radacina[rad1] = rad2;
}
vector<int> graf::disjoint(vector<pair<int,pair<int, int>>> operatii){
vector<int> radacina(NrNoduri + 1);
vector<int> rez;
for(int i = 0; i < NrNoduri; i++){
radacina[i] = i;
}
for(int i = 0; i < operatii.size(); i++){
int cod = operatii[i].first;
int x = operatii[i].second.first;
int y = operatii[i].second.second;
if(cod == 1){
uneste(x, y, radacina);
}
else{
if(cod == 2){
if(gaseste(x, radacina) == gaseste(y, radacina)){
rez.push_back(1);
}
else{
rez.push_back(0);
}
}
}
}
return rez;
}
int graf::diamArb(){
vector<int> vizitat(NrNoduri + 1, 0);
vector<int> distanta = BFS(1, vizitat);
int nodUltim, distMax = -1;
for(int i = 1; i < distanta.size(); i++){
if(distanta[i] > distMax){
distMax = distanta[i];
nodUltim = i;
}
}
for(int i = 0; i < vizitat.size(); i++){
vizitat[i] = 0;
}
distanta = BFS(nodUltim, vizitat);
distMax = -1;
for(int i = 1; i < distanta.size(); i++){
if(distanta[i] > distMax){
distMax = distanta[i];
}
}
return distMax;
}
bool compara(vector<int> v1, vector<int> v2){
return v1[2] < v2[2];
}
vector<int> grafCuCost::apm(int nod, int &costTotal){
vector<int> costMin(NrNoduri + 1, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> coadaPri;
vector<int> vizitat(NrNoduri + 1, 0);
vector<int> parinte(NrNoduri + 1, 0);
costMin[nod] = 0;
coadaPri.push({0, nod});
while(!coadaPri.empty()){
int nodCurent = coadaPri.top().second;
int costCurent = coadaPri.top().first;
coadaPri.pop();
if(!vizitat[nodCurent]){
vizitat[nodCurent] = 1;
costTotal += costCurent;
for(auto it : costuriVecini[nodCurent]){
if(!vizitat[it.second]){
int vecin = it.first.second;
int cost = it.second;
if(cost < costMin[vecin]){
costMin[vecin] = cost;
parinte[vecin] = nodCurent;
coadaPri.push({costMin[vecin], vecin});
}
}
}
}
}
return parinte;
}
vector<int> grafCuCost::Bellman_Ford(int nod){
vector<int> costMin(NrNoduri + 1, INT_MAX);
vector<int> vizitat(NrNoduri + 1, 0);
vector<int> inCoada(NrNoduri + 1, 0);
queue<int> coada;
costMin[nod] = 0;
coada.push(nod);
inCoada[nod] = 1;
while(!coada.empty()){
int nodCurent = coada.front();
vizitat[nodCurent]++;
if(vizitat[nodCurent] >= NrNoduri){
return {-1};
}
coada.pop();
inCoada[nodCurent] = 0;
for(auto i : costuriVecini[nodCurent]){
int vecin = i.first.second;
int cost = i.second;
if(costMin[nodCurent] + cost < costMin[vecin]){
costMin[vecin] = costMin[nodCurent] + cost;
if(!inCoada[vecin]){
coada.push(vecin);
inCoada[vecin] = 1;
}
}
}
}
return costMin;
}
vector<int> grafCuCost::Dijkstra(int nod){
vector<int> costMin(NrNoduri + 1, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> coadaPri;
vector<int> vizitat(NrNoduri + 1, 0);
costMin[nod] = 0;
coadaPri.push({0, nod});
while(!coadaPri.empty()){
int nodCurent = coadaPri.top().second;
coadaPri.pop();
if(!vizitat[nodCurent]){
vizitat[nodCurent] = 1;
for(auto i : costuriVecini[nodCurent]){
int vecin = i.first.second;
int cost = i.second;
if(costMin[nodCurent] + cost < costMin[vecin]){
costMin[vecin] = costMin[nodCurent] + cost;
coadaPri.push({costMin[vecin], vecin});
}
}
}
}
for(int i = 2; i <= NrNoduri; i++){
if(costMin[i] == INT_MAX){
costMin[i] = 0;
}
}
return costMin;
}
vector<vector<pair<pair<int, int>, int>>> grafCuCost::RoyFloyd(){
vector<vector<pair<pair<int, int>, int>>> rez = costuriVecini;
for(int i = 0; i < NrNoduri; i++){
for(int j = 0; j < NrNoduri; j++){
for(int k = 0; k < NrNoduri; k++){
if((j != k) && (rez[j][i].second) && (rez[i][k].second) && ((!rez[j][k].second) || (rez [j][k].second > rez[j][i].second + rez[i][k].second))){
rez[j][k].second = rez[j][i].second + rez[i][k].second;
}
}
}
}
return rez;
}
void InfoArena_BFS(){
int N, M, Sursa, x, y;
in>>N>>M>>Sursa;
graf G(N, M, true);
for(int i = 0; i < M; i++){
in>>x>>y;
G.setMuchii(x, y);
}
vector<int> vizitat(N + 1, 0);
vector<int> distanta;
G.BFS(Sursa, vizitat);
for(int i = 0; i < distanta.size(); i++){
if((distanta[i] == 0) && (Sursa != 1)){
out<<"-1";
}
else{
out<<distanta[i]<<" ";
}
}
}
void InfoArena_DFS(){
int N, M;
in>>N>>M;
graf G(N, M, false);
G.citireMuchii();
bool vizitat[N + 1] = {false};
out<<G.NrComponenteConexe(vizitat);
}
void InfoArena_disjoint(){
int N, M, cod, x, y;
in>>N>>M;
graf G(N, 0, false);
vector<pair<int, pair<int, int>>> operatii;
for(int i = 0; i < M; i++){
in>>cod>>x>>y;
operatii.push_back(make_pair(cod, make_pair(x, y)));
}
vector<int> rez = G.disjoint(operatii);
for(int i = 0; i < rez.size(); i++){
if(rez[i]){
out<<"DA"<<"\n";
}
else{
out<<"NU"<<"\n";
}
}
}
void InfoArena_apm(){
int N, M, X, Y, C;
in>>N>>M;
grafCuCost G(N, M, false);
for(int i = 0; i < M; i++){
in>>X>>Y>>C;
G.setMuchiiCost(X, Y, C);
}
int costTotal = 0;
vector<int> rez = G.apm(1, costTotal);
out<<costTotal<<"\n"<<rez.size()<<"\n";
for(int i = 0; i < rez.size(); i++){
out<<i<<" "<<rez[i]<<"\n";
}
}
void InfoArena_BellmanFord(){
int N, M, x, y, c;
in>>N>>M;
grafCuCost G(N, M, true);
for(int i = 0; i < M; i++){
in>>x>>y>>c;
G.setMuchiiCost(x, y, c);
}
vector<int> costMinim = G.Bellman_Ford(1);
if(costMinim[0] == -1){
out<<"Ciclu negativ!";
}
else{
for(int i = 2; i < costMinim.size(); i++){
out<<costMinim[i]<<" ";
}
}
}
void InfoArena_Dijkstra(){
int N, M, A, B, C;
in>>N>>M;
grafCuCost G(N, M, true);
for(int i = 0; i < M; i++){
in>>A>>B>>C;
G.setMuchiiCost(A, B, C);
}
vector<int> costMinim = G.Dijkstra(1);
for(int i = 2; i < costMinim.size(); i++){
out<<costMinim[i]<<" ";
}
}
void InfoArena_RoyFloyd(){
int N, cost;
in>>N;
grafCuCost G(N, 0, true);
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
in>>cost;
G.setMuchiiCost(i, j, cost);
}
}
vector<vector<pair<pair<int, int>, int>>> rez = G.RoyFloyd();
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
out<<rez[i][j].second<<" ";
}
out<<"\n";
}
}
void InfoArena_darb(){
int N, x, y;
in>>N;
graf G(N, N, false);
for(int i = 0; i < N; i++){
in>>x>>y;
G.setMuchii(x, y);
}
int rez = G.diamArb();
out<<rez + 1;
}
int main()
{
//InfoArena_BFS();
//InfoArena_DFS();
//InfoArena_disjoint();
//InfoArena_apm();
//InfoArena_BellmanFord();
//InfoArena_Dijkstra();
//InfoArena_RoyFloyd();
InfoArena_darb();
return 0;
}