#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll,ll>;
using Map = map<ll,ll>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
ll INF=1LL<<60;
ll MOD=1000000007;



int main(){
    ll N;
    cin >> N;
    vector<ll> L(N,0);
    vector<ll> R(N,0);
    ll recL=0;ll MaxL=0;
    for(ll i=0;i<N;i++){
        cin>>L[i]>>R[i];
        if(MaxL<L[i]){
            MaxL=L[i];
            recL=i;
        }
    ;}
    if(N==2){
        cout<<R[0]+R[1]-L[0]-L[1]+2<<endl;return 0;
    }
    vector<P> pq(0);
    for(ll i=0;i<N;i++){
        if(i!=recL)pq.push_back(P(R[i],L[i]))
    ;}
    sort(pq.begin(), pq.end());
    vector<ll> lmax(N-1,0);
    ll q=0;
    for(ll i=0;i<N-1;i++){
        q=max(q,pq[i].second);
        lmax[i]=q
    ;}
    //L[recL]が最大
    //最終的にrecL側のRの選考基準をｒとする
    //Rがpq[r]以上は仲間

    ll ans=0;

    //pq[0]が敵の時かつ仲間いるとき
    for(ll r=1;r<=N-2;r++){
        ans=max(ans,max(min(pq[r].first,R[recL])-MaxL+1,0LL)+max(pq[0].first-lmax[r-1]+1,0LL));
    ;}
    //全員敵
    ans=max(ans,max(pq[0].first-lmax[N-2]+1,0LL)+R[recL]-MaxL+1);
    //pq[0]が味方の時;
    ll ans2=0;
    ans2+=max(0LL,min(pq[0].first,R[recL])-MaxL+1);//味方
    ll check;
    for(ll i=0;i<N;i++){
        if(L[i]==pq[0].second&&R[i]==pq[0].first&&i!=recL){check=i;break;}
    ;}
    priority_queue<ll> vec;
    for(ll i=0;i<N;i++){
        if(i!=recL&&i!=check){
            vec.push(R[i]-L[i]+1);
        }
    ;}
    ans2+=vec.top();
    ans=max(ans,ans2);

    cout<<ans<<endl;


    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define debug(x) cerr<<#x<<":"<<x<<endl
#define fix cout<<fixed<<setprecision(20);
const int maxn=(int)2e6+5;
vector<int> E[maxn];
int vis[maxn],ind[maxn],dis[maxn];
int reach[maxn];//longest can reach
inline int id(int x,int y){
    if(x>y)swap(x,y);
    //x--,y--;
    return x+1000*y;
}
int ans=-1;

int dfs(int x){
    //debug(x);
    if(vis[x]==2)return dis[x];
    vis[x]=1;
    for(auto v:E[x]){
        if(vis[v]==1)return -1;
        
        //dis[v]=dis[x]+1;ans=max(ans,dis[v]);
        int ret=dfs(v);
        if(ret==-1)return -1;
        dis[x]=max(dis[x],ret+1);//每个节点存最大值。
        
        
    }
    
    //debug(dis[x]);debug(x);
    
    vis[x]=2;
    return dis[x];
}
int main(){
    //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;cin>>n;
    rep(i,1,n){
        int last=0;
        rep(j,1,n)if(i!=j){
            int x;scanf("%d",&x);
            if(last==0){last=id(i,x);continue;}
            E[last].push_back(id(i,x));ind[id(i,x)]++;
            last=id(i,x);
        }
    }
    
    rep(i,1,n)rep(j,1,i-1)if(ind[id(i,j)]==0){
       // memset(vis,0,sizeof(vis));
        E[0].push_back(id(i,j));
        /* dis[id(i,j)]=1;
        if(dfs(id(i,j))==0){cout<<-1<<endl;return 0;};
        //debug("--"); */
    }
    dis[0]=-1;
    int ans=dfs(0);
    
    cout<<ans<<endl;
    

}
/* 
建DAG，判环
topo 可判环（无法进入队列的点），但无法找最长路径
两种环
一种是链环，用
一种是纯环，
3
2 3
1 3
1 2

12-13
12-23
13-23

4
2 3 4
1 3 4
4 1 2
3 1 2

12-13
13-14
12-23
23-24
34-13
13-23
34-14
14-24

 queue<int> Q;
    rep(i,1,n)rep(j,1,i-1)if(ind[id(i,j)]==0)Q.push(id(i,j)),vis[id(i,j)]=1;
    while(!Q.empty()){
        
        int cur=Q.front();Q.pop();
        debug(cur);debug(vis[cur]);
        for(auto v:E[cur]){
            if(vis[v]){continue;}
            //if(vis[v]==1){cout<<-1<<endl;return 0;}
            ind[v]--;
            if(ind[v]==0)Q.push(v),vis[v]=vis[cur]+1,ans=max(ans,vis[v]);
        }
    }
   // rep(i,1,n)rep(j,1,n)if(i!=j)debug(vis[id(i,j)]),debug(i),debug(j);
 */