//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=1e6+100;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
pii t[4*N];
int la[4*N];
void push(int v,int tl,int tr){
    if(la[v] && 2*v+1<4*N){
        la[2*v]+=la[v];
        la[2*v+1]+=la[v];
        t[2*v].f+=la[v];
        t[2*v+1].f+=la[v];
        t[2*v].s+=la[v];
        t[2*v+1].s+=la[v];
        la[v]=0;
    }
}
void upd(int l,int r,int val,int v,int tl,int tr){
    if(tr<l || tl>r) return;
    if(tl>=l&&tr<=r){
        t[v].f+=val;
        t[v].s+=val;
        la[v]+=val;
        return ;
    }
    push(v,tl,tr);
    int tm=(tl+tr)>>1;
    upd(l,r,val,2*v,tl,tm);
    upd(l,r,val,2*v+1,tm+1,tr);
    t[v].f=min(t[2*v].f,t[2*v+1].f);
    t[v].s=max(t[2*v].s,t[2*v+1].s);
//    debug()<<imie(t[v]);
}
int kek[4*N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    int pos=1;
    string s;
    cin>>s;
    int k=0;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            upd(pos,N-1,w-pr,1,0,N-1);
            kek[pos]=w;
            k+=w-pr;
        }
        if(t[1].f==0){
            if(k==0){
                cout<<t[1].s;
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(t[1]);
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010fsdfs
110dadadasd
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=1e6+2;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
struct fnw{
    int f[N];
    void init(){
        fill(f,f+N,0);
    }
    void upd(int pos,int val){
        while(pos<N){
            f[pos]+=val;
            pos+=pos&-pos;
        }
    }
    int get(int pos){
        int val=0;
        while(pos>0){
            val+=f[pos];
            pos-=pos&-pos;
        }
        return val;
    }
}a;
struct DO{
    int tp;
    int tree[4*N];
    int ex(int type){
        int to;
        if(tp==2) to=2e9;
        else if(tp==3) to=-2e9;
        return to;
    }
    void init(int type){
        tp=type;
        fill(tree,tree+4*N,ex(tp));
    }
    int pull(int a,int b){
        if(tp==1) return a+b;
        else if(tp==2) return min(a,b);
        else return max(a,b);
    }
    void upd(int pos,int val,int v,int tl,int tr){
        if(tl==tr){
            tree[v]=val;return;
        }
        int tm=(tl+tr)>>1;
        if(tm>=pos)upd(pos,val,2*v,tl,tm);
        else upd(pos,val,2*v+1,tm+1,tr);
        tree[v]=pull(tree[2*v],tree[2*v+1]);
    }
}b,c;
int kek[N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    a.init();
    b.init(2);
    c.init(3);
    int pos=1;
    string s;
    cin>>s;
    int k=0;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            a.upd(pos,w-pr);
            int nw=a.get(pos);
            kek[pos]=w;k+=w-pr;
//            debug()<<imie(a.get(pos));
            b.upd(pos,nw,1,0,N-1);
            c.upd(pos,nw,1,0,N-1);
        }
        if(b.tree[1]==0){
            if(k==0){
                cout<<c.tree[1];
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010fsdfs
110dadadasd
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=2e6+100;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
pii t[4*N];
int la[4*N];
void push(int v,int tl,int tr){
    if(la[v] && 2*v+1<4*N){
        la[2*v]+=la[v];
        la[2*v+1]+=la[v];
        t[2*v].f+=la[v];
        t[2*v+1].f+=la[v];
        t[2*v].s+=la[v];
        t[2*v+1].s+=la[v];
        la[v]=0;
    }
}
void upd(int l,int r,int val,int v,int tl,int tr){
    if(tr<l || tl>r) return;
    if(tl>=l&&tr<=r){
        t[v].f+=val;
        t[v].s+=val;
        la[v]+=val;
        return ;
    }
    push(v,tl,tr);
    int tm=(tl+tr)>>1;
    upd(l,r,val,2*v,tl,tm);
    upd(l,r,val,2*v+1,tm+1,tr);
    t[v].f=min(t[2*v].f,t[2*v+1].f);
    t[v].s=max(t[2*v].s,t[2*v+1].s);
//    debug()<<imie(t[v]);
}
int kek[N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    int pos=N;
    string s;
    cin>>s;
    int k=0;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            upd(pos,N-1,w-pr,1,0,N-1);
            kek[pos]=w;
            k+=w-pr;
        }
        if(t[1].f==0){
            if(k==0){
                cout<<t[1].s;
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(t[1]);
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010fsdfs
110dadadasd
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=1e6+2;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
struct fnw{
    int tp;
    int f[N];
    void init(int type){
        tp=type;
        fill(f,f+N,0);
    }
    void pull(int &a,int b){
        if(tp==1) a+=b;
        else if(tp==2) umin(a,b);
        else umax(a,b);
    }
    void upd(int pos,int val){
        while(pos<N){
            pull(f[pos],val);
            pos+=pos&-pos;
        }
    }
    int get(int pos){
        int val;
        if(tp==1) val=0;
        else if(tp==2) val=2e9;
        else val=-2e9;
        while(pos>0){
            pull(val,f[pos]);
            pos-=pos&-pos;
        }
        return val;
    }
}a;
struct DO{
    int tp;
    int tree[4*N];
    int ex(int type){
        int to;
        if(tp==2) to=2e9;
        else if(tp==3) to=-2e9;
        return to;
    }
    void init(int type){
        tp=type;
        fill(tree,tree+4*N,ex(tp));
    }
    int pull(int a,int b){
        if(tp==1) return a+b;
        else if(tp==2) return min(a,b);
        else return max(a,b);
    }
    void upd(int pos,int val,int v,int tl,int tr){
        if(tl==tr){
            tree[v]=val;return;
        }
        int tm=(tl+tr)>>1;
        if(tm>=pos)upd(pos,val,2*v,tl,tm);
        else upd(pos,val,2*v+1,tm+1,tr);
        tree[v]=pull(tree[2*v],tree[2*v+1]);
    }
}b,c;
signed main()
{
    fast_io;
    int n;
    cin>>n;
    a.init(1);
    b.init(2);
    c.init(3);
    int pos=1;
    string s;
    cin>>s;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            a.upd(pos,w);
            int nw=a.get(pos);
//            debug()<<imie(a.get(pos));
            b.upd(pos,nw,1,0,N-1);
            c.upd(pos,nw,1,0,N-1);
        }
        if(b.tree[1]==0){
            if(a.get(N-1)==0){
                cout<<c.tree[1];
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010
110
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=2e6+100;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
pii t[4*N];
int la[4*N];
void push(int v,int tl,int tr){
    if(la[v] && 2*v+1<4*N){
        la[2*v]+=la[v];
        la[2*v+1]+=la[v];
        t[2*v].f+=la[v];
        t[2*v+1].f+=la[v];
        t[2*v].s+=la[v];
        t[2*v+1].s+=la[v];
        la[v]=0;
    }
}
void upd(int l,int r,int val,int v,int tl,int tr){
    if(tr<l || tl>r) return;
    if(tl>=l&&tr<=r){
        t[v].f+=val;
        t[v].s+=val;
        la[v]+=val;
        return ;
    }
    push(v,tl,tr);
    int tm=(tl+tr)>>1;
    upd(l,r,val,2*v,tl,tm);
    upd(l,r,val,2*v+1,tm+1,tr);
    t[v].f=min(t[2*v].f,t[2*v+1].f);
    t[v].s=max(t[2*v].s,t[2*v+1].s);
//    debug()<<imie(t[v]);
}
int kek[N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    int pos=N/2;
    string s;
    cin>>s;
    int k=0;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            upd(pos,N-1,w-pr,1,0,N-1);
            kek[pos]=w;
            k+=w-pr;
        }
        if(t[1].f==0){
            if(k==0){
                cout<<t[1].s;
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(t[1]);
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010fsdfs
110dadadasd
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=1e6+2;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
struct fnw{
    int f[N];
    void init(){
        fill(f,f+N,0);
    }
    void upd(int pos,int val){
        while(pos<N){
            f[pos]+=val;
            pos+=pos&-pos;
        }
    }
    int get(int pos){
        int val=0;
        while(pos>0){
            val+=f[pos];
            pos-=pos&-pos;
        }
        return val;
    }
}a;
struct DO{
    int tp;
    int tree[4*N];
    int ex(int type){
        int to;
        if(tp==2) to=2e9;
        else if(tp==3) to=-2e9;
        return to;
    }
    void init(int type){
        tp=type;
        fill(tree,tree+4*N,ex(tp));
    }
    int pull(int a,int b){
        if(tp==1) return a+b;
        else if(tp==2) return min(a,b);
        else return max(a,b);
    }
    void upd(int pos,int val,int v,int tl,int tr){
        if(tl==tr){
            tree[v]=val;return;
        }
        int tm=(tl+tr)>>1;
        if(tm>=pos)upd(pos,val,2*v,tl,tm);
        else upd(pos,val,2*v+1,tm+1,tr);
        tree[v]=pull(tree[2*v],tree[2*v+1]);
    }
}b,c;
int kek[N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    a.init();
    b.init(2);
    c.init(3);
    int pos=1;
    string s;
    cin>>s;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            a.upd(pos,w-pr);
            int nw=a.get(pos);
            kek[pos]=nw;
//            debug()<<imie(a.get(pos));
            b.upd(pos,nw,1,0,N-1);
            c.upd(pos,nw,1,0,N-1);
        }
        if(b.tree[1]==0){
            if(a.get(N-1)==0){
                cout<<c.tree[1];
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010
110
*/


//C.cpp
#include<bits/stdc++.h>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/tree_policy.hpp>
//
//    #pragma GCC optimize("-O3")
////    #pragma GCC optimize("no-stack-protector")
//    #pragma GCC optimize("fast-math")
//    #pragma GCC optimize("Ofast")
//    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
//    #pragma GCC target("avx,avx2,fma")
//    #pragma GCC optimization ("unroll-loops")
//#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifndef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
	*this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define fi first
#define f first
#define se second
#define s second
#define vi_a vector<int>a;
#define p_b push_back
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ll long long
typedef unsigned long long ull;
////////////////////////////////???????????????CHECK THIS OUT???????????????//////////////////////////////
#define ld long double
#define pll pair<ll,ll>
#define pii pair<int,int>
#define m_p make_pair
#define fast_io cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);
#define all(x) x.begin(),x.end()
#define getfiles    ifstream cin("input.txt");ofstream cout("output.txt");
#define pw(x) (1ll << x)
#define sz(x) (int)x.size()
#define endl "\n"
#define rall(x) x.rbegin(),x.rend()
#define len(a) (ll)a.size()
#define rep(x,l,r) for(ll x=l;x<r;x++)

//using namespace __gnu_pbds;
ld eps = (ld)1 / 1e6;
const ld pi=3.14159265359;
ll inf = 1e18,mod1=1e9+7;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
template<typename T> bool umax(T& a, T b) {return a<b?a=b,1:0;}
template<typename T> bool umin(T& a, T b) {return b<a?a=b,1:0;}
bool is_prime(ll val){for(ll i=2;i<=sqrt(val);i++)if(val%i==0)return 0; return 1;}
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const ll RR=1e4;
const ll tx[8]={1,-1,2,-2,-1,-2};
const ll ty[8]={-2,-2,-1,-1,2,1};
const char rev_to[4]={'E','W','N','S'};
const int M=1e9+7;
const int N=1e6+100;
const int ppp=73;
const int pr=3;
const int block=320;
const int OPEN=1;
const int CLOSE=0;
typedef pair<long long,int> pli;
//typedef tree<pli,null_type,less<pli>,rb_tree_tag,tree_order_statistics_node_update> o_st;
auto rnd=bind(uniform_int_distribution<ll>(1,125),mt19937(time(0)));
void bad(){
    cout<<"-1";
    exit(0);
}
pii t[4*N];
int la[4*N];
void push(int v,int tl,int tr){
    if(la[v] && 2*v+1<4*N){
        la[2*v]+=la[v];
        la[2*v+1]+=la[v];
        t[2*v].f+=la[v];
        t[2*v+1].f+=la[v];
        t[2*v].s+=la[v];
        t[2*v+1].s+=la[v];
        la[v]=0;
    }
}
void upd(int l,int r,int val,int v,int tl,int tr){
    if(tr<l || tl>r) return;
    if(tl>=l&&tr<=r){
        t[v].f+=val;
        t[v].s+=val;
        la[v]+=val;
        return ;
    }
    push(v,tl,tr);
    int tm=(tl+tr)>>1;
    upd(l,r,val,2*v,tl,tm);
    upd(l,r,val,2*v+1,tm+1,tr);
    t[v].f=min(t[2*v].f,t[2*v+1].f);
    t[v].s=max(t[2*v].s,t[2*v+1].s);
//    debug()<<imie(t[v]);
}
int kek[N];
signed main()
{
    fast_io;
    int n;
    cin>>n;
    int pos=1;
    string s;
    cin>>s;
    int k=0;
    for(auto &z : s){
        if(z=='R')pos++;
        else if(z=='L') pos--;
        else{
            int w;
            int pr=kek[pos];
            if(z=='(') w=1;
            else if(z==')') w=-1;
            else w=0;
            upd(pos,N-1,w-pr,1,0,N-1);
            kek[pos]=w;
            k+=w-pr;
        }
        if(t[1].f==0){
            if(k==0){
                cout<<t[1].s;
            }else cout<<-1;
        }else cout<<-1;
        cout<<' ';
//        debug()<<imie(t[1]);
//        debug()<<imie(pos);
    }
    return 0;
}
/*
3 3
001
010fsdfs
110dadadasd
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

#define fo(i,n) for(i=0;i<n;i++)
#define Fo(i,k,n) for(i=k;i<n;i++)
#define ll long long
typedef unsigned long long ul;

#define pi pair < ll , ll >
#define pb push_back
#define mp make_pair
#define F first
#define S second

#define fastIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define debug(x) cout<<#x<<" :: "<<x<<"\n";
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\n";
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\n";

typedef tree< ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//DP Practice for 2 days
ll vis[1001], dp[1001], dp2[1001], ht[1001];
vector < ll > graph[1001];
ll mx, nde, mdl;
void dfs(ll node, ll parent)
{
    vis[node] = 1;
    if(ht[node]>=mx){mx=ht[node];nde = node;}
    if(ht[node]==((mx)/2) and dp[node]==((mx+1)/2))mdl = node;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        ht[x] = ht[node] + 1;
        dfs(x, node);
    }
}
void dfs2(ll node, ll parent)
{
    ll mx = 0;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        dfs(x, node);
        mx = max(mx, dp[x] + 1);
    }
    dp[node] = mx;
}
int main()
{
    fastIO;
    ll n, m, i, j, k, ans = 0, cent, idx;
    vector < pair < ll , ll > > mids;
    cin>>n>>m;
    fo(i,m)
    {
        cin>>j>>k;
        graph[j].pb(k);
        graph[k].pb(j);
    }
    if(m==0)
    {
        if(n==1)cout<<0<<endl;
        else if(n==2)cout<<1<<endl;
        else cout<<2<<endl;
        fo(i,n-1)cout<<1<<" "<<i+2<<endl;
        return 0;
    }
    Fo(i, 1, n+1)
    {
        if(vis[i]==1)continue;
        ht[i] = 0;
        mx = 0;
        dfs(i, 0);
        ll xyz = nde;
        ht[xyz] = 0;
        dfs(xyz, 0);
        if(ans<mx)
        {
            ans = mx;
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            cent = mdl;
            idx = mids.size();
            mids.pb({(mx+1)/2, cent});
        }
        else
        {
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            mids.pb({(mx+1)/2, mdl});
        }
    }
    i = 0;
    ll tvtv = ans;
    for(auto x:mids)
    {
        if(i!=idx)ans = max(ans, (tvtv+1)/2 + x.F + 1);
        i++;
    }
    cout<<ans<<endl;
    i=0;
    for(auto x:mids)
    {
        if(i!=idx)cout<<cent<<" "<<x.S<<endl;
        i++;
    }

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

#define fo(i,n) for(i=0;i<n;i++)
#define Fo(i,k,n) for(i=k;i<n;i++)
#define ll long long
typedef unsigned long long ul;

#define pi pair < ll , ll >
#define pb push_back
#define mp make_pair
#define F first
#define S second

#define fastIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define debug(x) cout<<#x<<" :: "<<x<<"\n";
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\n";
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\n";

typedef tree< ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//DP Practice for 2 days
ll vis[1001], dp[1001], dp2[1001], ht[1001];
vector < ll > graph[1001];
ll mx, nde, mdl;
void dfs(ll node, ll parent)
{
    vis[node] = 1;
    if(ht[node]>=mx){mx=ht[node];nde = node;}
    if(ht[node]==((mx)/2))mdl = node;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        ht[x] = ht[node] + 1;
        dfs(x, node);
    }
}
int main()
{
    fastIO;
    ll n, m, i, j, k, ans = 0, cent, idx;
    vector < pair < ll , ll > > mids;
    cin>>n>>m;
    fo(i,m)
    {
        cin>>j>>k;
        graph[j].pb(k);
        graph[k].pb(j);
    }
    if(m==0)
    {
        if(n==1)cout<<0<<endl;
        else if(n==2)cout<<1<<endl;
        else cout<<2<<endl;
        fo(i,n-1)cout<<1<<" "<<i+2<<endl;
        return 0;
    }
    Fo(i, 1, n+1)
    {
        if(vis[i]==1)continue;
        ht[i] = 0;
        mx = 0;
        dfs(i, 0);
        mx = 0;
        ll xyz = nde;
        ht[xyz] = 0;
        dfs(xyz, 0);
        if(ans<mx)
        {
            ans = mx;
            ht[xyz] = 0;
            dfs(xyz, 0);
            cent = mdl;
            idx = mids.size();
            mids.pb({(mx+1)/2, cent});
        }
        else
        {
            ht[nde] = 0;
            dfs(nde, 0);
            mids.pb({(mx+1)/2, mdl});
        }
    }
    i = 0;
    ll tvtv = ans;
    for(auto x:mids)
    {
        if(i!=idx)ans = max(ans, (tvtv+1)/2 + x.F + 1);
        i++;
    }
    cout<<ans<<endl;
    i=0;
    for(auto x:mids)
    {
        if(i!=idx)cout<<cent<<" "<<x.S<<endl;
        i++;
    }

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

#define fo(i,n) for(i=0;i<n;i++)
#define Fo(i,k,n) for(i=k;i<n;i++)
#define ll long long
typedef unsigned long long ul;

#define pi pair < ll , ll >
#define pb push_back
#define mp make_pair
#define F first
#define S second

#define fastIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define debug(x) cout<<#x<<" :: "<<x<<"\n";
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\n";
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\n";

typedef tree< ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//DP Practice for 2 days
ll vis[1001], dp[1001], dp2[1001], ht[1001];
vector < ll > graph[1001];
ll mx, nde, mdl;
void dfs(ll node, ll parent)
{
    vis[node] = 1;
    if(ht[node]>=mx){mx=ht[node];nde = node;}
    if(ht[node]==((mx)/2))mdl = node;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        ht[x] = ht[node] + 1;
        dfs(x, node);
    }
}
int main()
{
    fastIO;
    ll n, m, i, j, k, ans = 0, cent, idx;
    vector < pair < ll , ll > > mids;
    cin>>n>>m;
    fo(i,m)
    {
        cin>>j>>k;
        graph[j].pb(k);
        graph[k].pb(j);
    }
    if(m==0)
    {
        if(n==1)cout<<0<<endl;
        else if(n==2)cout<<1<<endl;
        else cout<<2<<endl;
        fo(i,n-1)cout<<1<<" "<<i+2<<endl;
        return 0;
    }
    Fo(i, 1, n+1)
    {
        if(vis[i]==1)continue;
        ht[i] = 0;
        mx = 0;
        dfs(i, 0);
        ll xyz = nde;
        ht[xyz] = 0;
        dfs(xyz, 0);
        if(ans<mx)
        {
            ans = mx;
            ht[xyz] = 0;
            dfs(xyz, 0);
            cent = mdl;
            idx = mids.size();
            mids.pb({(mx+1)/2, cent});
        }
        else
        {
            ht[xyz] = 0;
            dfs(xyz, 0);
            mids.pb({(mx+1)/2, mdl});
        }
    }
    i = 0;
    ll tvtv = ans;
    for(auto x:mids)
    {
        if(i!=idx)ans = max(ans, (tvtv+1)/2 + x.F + 1);
        i++;
    }
    cout<<ans<<endl;
    i=0;
    for(auto x:mids)
    {
        if(i!=idx)cout<<cent<<" "<<x.S<<endl;
        i++;
    }

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

#define fo(i,n) for(i=0;i<n;i++)
#define Fo(i,k,n) for(i=k;i<n;i++)
#define ll long long
typedef unsigned long long ul;

#define pi pair < ll , ll >
#define pb push_back
#define mp make_pair
#define F first
#define S second

#define fastIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define debug(x) cout<<#x<<" :: "<<x<<"\n";
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\n";
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\n";

typedef tree< ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//DP Practice for 2 days
ll vis[1001], dp[1001], dp2[1001], ht[1001];
vector < ll > graph[1001];
ll mx, nde, mdl;
void dfs(ll node, ll parent)
{
    vis[node] = 1;
    if(ht[node]>=mx){mx=ht[node];nde = node;}
    if(ht[node]==((mx)/2) and dp[node]==((mx+1)/2))mdl = node;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        ht[x] = ht[node] + 1;
        dfs(x, node);
    }
}
void dfs2(ll node, ll parent)
{
    ll mx = 0;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        dfs2(x, node);
        mx = max(mx, dp[x] + 1);
    }
    dp[node] = mx;
}
int main()
{
    fastIO;
    ll n, m, i, j, k, ans = 0, cent, idx;
    vector < pair < ll , ll > > mids;
    cin>>n>>m;
    fo(i,m)
    {
        cin>>j>>k;
        graph[j].pb(k);
        graph[k].pb(j);
    }
    if(m==0)
    {
        if(n==1)cout<<0<<endl;
        else if(n==2)cout<<1<<endl;
        else cout<<2<<endl;
        fo(i,n-1)cout<<1<<" "<<i+2<<endl;
        return 0;
    }
    Fo(i, 1, n+1)
    {
        if(vis[i]==1)continue;
        ht[i] = 0;
        mx = 0;
        dfs(i, 0);
        ll xyz = nde;
        ht[xyz] = 0;
        dfs(xyz, 0);
        if(ans<mx)
        {
            ans = mx;
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            cent = mdl;
            idx = mids.size();
            mids.pb({(mx+1)/2, cent});
        }
        else
        {
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            mids.pb({(mx+1)/2, mdl});
        }
    }
    i = 0;
    ll tvtv = ans;
    for(auto x:mids)
    {
        if(i!=idx)ans = max(ans, (tvtv+1)/2 + x.F + 1);
        i++;
    }
    cout<<ans<<endl;
    i=0;
    for(auto x:mids)
    {
        if(i!=idx)cout<<cent<<" "<<x.S<<endl;
        i++;
    }

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;

#define fo(i,n) for(i=0;i<n;i++)
#define Fo(i,k,n) for(i=k;i<n;i++)
#define ll long long
typedef unsigned long long ul;

#define pi pair < ll , ll >
#define pb push_back
#define mp make_pair
#define F first
#define S second

#define fastIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define debug(x) cout<<#x<<" :: "<<x<<"\n";
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\n";
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\n";

typedef tree< ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
//DP Practice for 2 days
ll vis[1001], dp[1001], dp2[1001], ht[1001];
vector < ll > graph[1001];
ll mx, nde, mdl;
void dfs(ll node, ll parent)
{
    vis[node] = 1;
    if(ht[node]>=mx){mx=ht[node];nde = node;}
    if(ht[node]==((mx)/2) and dp[node]==((mx+1)/2))mdl = node;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        ht[x] = ht[node] + 1;
        dfs(x, node);
    }
}
void dfs2(ll node, ll parent)
{
    ll mx = 0;
    for(auto x:graph[node])
    {
        if(x==parent)continue;
        dfs2(x, node);
        mx = max(mx, dp[x] + 1);
    }
    dp[node] = mx;
}
int main()
{
    fastIO;
    ll n, m, i, j, k, ans = 0, cent, idx;
    vector < pair < ll , ll > > mids;
    cin>>n>>m;
    fo(i,m)
    {
        cin>>j>>k;
        graph[j].pb(k);
        graph[k].pb(j);
    }
    if(m==0)
    {
        if(n==1)cout<<0<<endl;
        else if(n==2)cout<<1<<endl;
        else cout<<2<<endl;
        fo(i,n-1)cout<<1<<" "<<i+2<<endl;
        return 0;
    }
    Fo(i, 1, n+1)
    {
        if(vis[i]==1)continue;
        ht[i] = 0;
        mx = 0;
        dfs(i, 0);
        ll xyz = nde;
        ht[xyz] = 0;
        dfs(xyz, 0);
        if(ans<mx)
        {
            ans = mx;
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            cent = mdl;
            idx = mids.size();
            mids.pb({(mx+1)/2, cent});
        }
        else
        {
            ht[xyz] = 0;
            dfs2(xyz, 0);
            dfs(xyz, 0);
            mids.pb({(mx+1)/2, mdl});
        }
    }
    i = 0;
    ll tvtv = ans;
    for(auto x:mids)
    {
        if(i!=idx)ans = max(ans, (ans+1)/2 + x.F + 1);
        i++;
    }
    cout<<ans<<endl;
    i=0;
    for(auto x:mids)
    {
        if(i!=idx)cout<<cent<<" "<<x.S<<endl;
        i++;
    }

}


#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <unordered_set>
#include <cmath>
#include <complex>
#include <deque>
#include <iterator>
#include <numeric>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <limits>
#include <iomanip>
#include <functional>
#include <cassert>
using namespace std;

using ll=long long;
template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
using vll = V<ll>;
using vvll = V<vll>;
#define rep(i, k, n) for (ll i=k; i<(ll)n; ++i)
#define REP(i, n) rep(i, 0, n)
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, T b) {if (a>b) {a=b; return true;} return false;}
#define DEBUG_VLL(vec) REP(sz, vec.size()) cerr<<vec[sz]<<(sz==vec.size()-1?'\n':' ');

constexpr ll MOD = 1000000007;
constexpr ll HIGHINF = (ll)1e18;
constexpr int INF = 1e9;

int n, m;
V< V<int> > edges;
V<bool> used;
V<int> dist;
V<int> fromn;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> m;
    edges.resize(n);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        u--, v--;
        edges[u].emplace_back(v);
        edges[v].emplace_back(u);
    }

    used.resize(n, false);
    dist.resize(n, 0);
    fromn.resize(n, -1);
    V< V<int> > paths;
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        V<int> nodes;
        queue<int> que; que.push(i);
        dist[i] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    que.push(e);
                }
            }
        }

        int node1, node2, maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node1 = node;
            used[node] = false;
        }

        que.push(node1);
        dist[node1] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    fromn[e] = q;
                    que.push(e);
                }
            }
        }

        maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node2 = node;
        }

        V<int> path;
        while (node2 != -1) {
            path.emplace_back(node2);
            node2 = fromn[node2];
        }
        paths.emplace_back(path);
    }
    sort(ALL(paths), [&](V<int> &i, V<int>&j) {
        return i.size() > j.size();
    });

    int ansd = paths[0].size() - 1;
    V< P<int, int> > con;
    int basenode = paths[0][paths[0].size() >> 1];
    for (int i = 1; i < paths.size(); i++) {
        con.emplace_back(basenode, paths[i][paths[i].size() >> 1]);
        chmax(ansd, (ansd + 1) / 2 + (int)paths[i].size() / 2 + 1);
    }

    cout << ansd << '\n';
    for (int i = 0; i < con.size(); i++) cout << con[i].fi + 1 << ' ' << con[i].se + 1 << '\n';
    return 0;
}


#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <unordered_set>
#include <cmath>
#include <complex>
#include <deque>
#include <iterator>
#include <numeric>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <limits>
#include <iomanip>
#include <functional>
#include <cassert>
using namespace std;

using ll=long long;
template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
using vll = V<ll>;
using vvll = V<vll>;
#define rep(i, k, n) for (ll i=k; i<(ll)n; ++i)
#define REP(i, n) rep(i, 0, n)
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, T b) {if (a>b) {a=b; return true;} return false;}
#define DEBUG_VLL(vec) REP(sz, vec.size()) cerr<<vec[sz]<<(sz==vec.size()-1?'\n':' ');

constexpr ll MOD = 1000000007;
constexpr ll HIGHINF = (ll)1e18;
constexpr int INF = 1e9;

int n, m;
V< V<int> > edges;
V<bool> used;
V<int> dist;
V<int> fromn;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> m;
    edges.resize(n);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        u--, v--;
        edges[u].emplace_back(v);
        edges[v].emplace_back(u);
    }

    used.resize(n, false);
    dist.resize(n, 0);
    fromn.resize(n, -1);
    V< V<int> > paths;
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        V<int> nodes;
        queue<int> que; que.push(i);
        dist[i] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    que.push(e);
                }
            }
        }

        int node1, node2, maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node1 = node;
            used[node] = false;
        }

        que.push(node1);
        dist[node1] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    fromn[e] = q;
                    que.push(e);
                }
            }
        }

        maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node2 = node;
        }

        V<int> path;
        while (node2 != -1) {
            path.emplace_back(node2);
            node2 = fromn[node2];
        }
        paths.emplace_back(path);
    }
    sort(ALL(paths), [&](V<int> &i, V<int>&j) {
        return i.size() > j.size();
    });

    int ansd = paths[0].size() - 1;
    V< P<int, int> > con;
    int basenode = paths[0][paths[0].size() >> 1];
    for (int i = 1; i < paths.size(); i++) {
        con.emplace_back(basenode, paths[i][paths[i].size() >> 1]);
        chmax(ansd, (int)paths[0].size() / 2 + (int)paths[i].size() / 2 + 1);
    }

    cout << ansd << '\n';
    for (int i = 0; i < con.size(); i++) cout << con[i].fi + 1 << ' ' << con[i].se + 1 << '\n';
    return 0;
}


#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <unordered_set>
#include <cmath>
#include <complex>
#include <deque>
#include <iterator>
#include <numeric>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <limits>
#include <iomanip>
#include <functional>
#include <cassert>
using namespace std;

using ll=long long;
template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
using vll = V<ll>;
using vvll = V<vll>;
#define rep(i, k, n) for (ll i=k; i<(ll)n; ++i)
#define REP(i, n) rep(i, 0, n)
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, T b) {if (a>b) {a=b; return true;} return false;}
#define DEBUG_VLL(vec) REP(sz, vec.size()) cerr<<vec[sz]<<(sz==vec.size()-1?'\n':' ');

constexpr ll MOD = 1000000007;
constexpr ll HIGHINF = (ll)1e18;
constexpr int INF = 1e9;

int n, m;
V< V<int> > edges;
V<bool> used;
V<int> dist;
V<int> fromn;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> m;
    edges.resize(n);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        u--, v--;
        edges[u].emplace_back(v);
        edges[v].emplace_back(u);
    }

    used.resize(n, false);
    dist.resize(n, 0);
    fromn.resize(n, -1);
    int basenode = -1;
    int ansd = 0;
    V< P<int, int> > con;
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        V<int> nodes;
        queue<int> que; que.push(i);
        dist[i] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    que.push(e);
                }
            }
        }

        int node1, node2, maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node1 = node;
            used[node] = false;
        }

        que.push(node1);
        dist[node1] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    fromn[e] = q;
                    que.push(e);
                }
            }
        }

        maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node2 = node;
        }

        V<int> path;
        while (node2 != -1) {
            path.emplace_back(node2);
            node2 = fromn[node2];
        }

        if (basenode == -1) {
            ansd = maxd;
            basenode = path[(int)path.size() / 2];
        } else {
            if (ansd >= maxd) {
                con.emplace_back(mp(basenode, path[(int)path.size() / 2]));
            } else {
                con.emplace_back(mp(basenode, path[(int)path.size() / 2]));
                basenode = path[(int)path.size() / 2];
            }
            chmax(ansd, max(maxd, (ansd + 1) / 2 + (maxd + 1) / 2 + 1));
        }
    }
    cout << ansd << '\n';
    for (int i = 0; i < con.size(); i++) cout << con[i].fi + 1 << ' ' << con[i].se + 1 << '\n';
    return 0;
}


#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <unordered_set>
#include <cmath>
#include <complex>
#include <deque>
#include <iterator>
#include <numeric>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <limits>
#include <iomanip>
#include <functional>
#include <cassert>
using namespace std;

using ll=long long;
template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
using vll = V<ll>;
using vvll = V<vll>;
#define rep(i, k, n) for (ll i=k; i<(ll)n; ++i)
#define REP(i, n) rep(i, 0, n)
#define ALL(v) v.begin(),v.end()
#define mp(a, b) make_pair(a, b)
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, T b) {if (a>b) {a=b; return true;} return false;}
#define DEBUG_VLL(vec) REP(sz, vec.size()) cerr<<vec[sz]<<(sz==vec.size()-1?'\n':' ');

constexpr ll MOD = 1000000007;
constexpr ll HIGHINF = (ll)1e18;
constexpr int INF = 1e9;

int n, m;
V< V<int> > edges;
V<bool> used;
V<int> dist;
V<int> fromn;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> m;
    edges.resize(n);
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v;
        u--, v--;
        edges[u].emplace_back(v);
        edges[v].emplace_back(u);
    }

    used.resize(n, false);
    dist.resize(n, 0);
    fromn.resize(n, -1);
    int basenode = -1;
    int ansd = 0;
    V< P<int, int> > con;
    for (int i = 0; i < n; i++) {
        if (used[i]) continue;
        V<int> nodes;
        queue<int> que; que.push(i);
        dist[i] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    que.push(e);
                }
            }
        }

        int node1, node2, maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node1 = node;
            used[node] = false;
        }

        que.push(node1);
        dist[node1] = 0;
        while (!que.empty()) {
            int q = que.front(); que.pop();
            if (used[q]) continue;
            used[q] = true;
            nodes.emplace_back(q);
            for (int e: edges[q]) {
                if (!used[e]) {
                    dist[e] = dist[q] + 1;
                    fromn[e] = q;
                    que.push(e);
                }
            }
        }

        maxd = -1;
        for (int node: nodes) {
            if (chmax(maxd, dist[node])) node2 = node;
        }

        V<int> path;
        while (node2 != -1) {
            path.emplace_back(node2);
            node2 = fromn[node2];
        }

        if (basenode == -1) {
            ansd = maxd;
            basenode = path[(int)path.size() / 2];
        } else {
            if (ansd >= maxd) {
                con.emplace_back(mp(basenode, path[(int)path.size() / 2]));
            } else {
                con.emplace_back(mp(basenode, path[(int)path.size() / 2]));
                basenode = path[(int)path.size() / 2];
            }
            chmax(ansd, (ansd + 1) / 2 + (maxd + 1) / 2 + 1);
        }
    }
    cout << ansd << '\n';
    for (int i = 0; i < con.size(); i++) cout << con[i].fi + 1 << ' ' << con[i].se + 1 << '\n';
    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1002;
int n,m,vis[N],dis[N];

vector<int> g[N];

int bfs(int u){
    queue<int> q; q.push(u); vis[u]=1;
    vector<int> vec;
    while(q.size()){
        int u=q.front(); q.pop();
        vec.push_back(u);
        for(auto v:g[u]){
            if(vis[v]==1)continue;
            vis[v]=1; q.push(v); dis[v]=dis[u]+1;
        }
    }
    int bst=0,mx=0;
    for(auto x:vec) {
        if(dis[x]>=mx) {
            mx=dis[x]; bst=x;
        }
    }
    return bst;
}

pair<int,int> getD(int src) {
    bool v[N]={0}; int pre[N]={0},d[N]={0};
    vector<int> vec;
    queue<int> q; q.push(src); v[src]=1;
    while(q.size()){
        int u=q.front(); q.pop(); vec.push_back(u);
        //printf("d[%d]=%d\n", u,d[u]);
        for(auto x:g[u]){
            if(v[x]==1)continue;
            v[x]=1; q.push(x); d[x]=d[u]+1;
            pre[x]=u;
        }
    }
    int len=0,bst=0;
    for(auto i: vec){
        if(d[i]>=len) {
            len=d[i]; bst=i;
        }
    }
    int now=bst;
    while(d[now]>len/2) now=pre[now];
    return make_pair(len,now);
}

vector< pair<int,int> > vec;
pair<int,int> ans[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v); g[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0) {
            int rt = bfs(i);
            //printf("rt = %d\n", rt);
            pair<int,int> p = getD(rt);
            vec.push_back(p);
            //printf("(%d, %d)\n", p.first, p.second);
        }
    }
    sort(vec.begin(),vec.end());
    int L=501,R=500;
    for(int i=vec.size()-1;i>=0;i--) {
        if(i%2==0) ans[--L]=vec[i];
        else ans[++R]=vec[i];
    }
    //printf("[%d, %d]\n", L,R);
    int mx=0;
    for(int i=L;i<=R;i++)for(int j=i;j<=R;j++){
        if(i!=j)
        mx = max(mx, (ans[i].first+1)/2 + (ans[j].first+1)/2 + j-i);
        else
        mx = max(mx, ans[i].first);
    }
    printf("%d\n", mx);
    for(int i=L;i<R;i++) {
        printf("%d %d\n", ans[i].second, ans[i+1].second);
    }
}


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1022;
int n,m,vis[N],dis[N];

vector<int> g[N];

int bfs(int u){
    queue<int> q; q.push(u); vis[u]=1;
    vector<int> vec;
    while(q.size()){
        int u=q.front(); q.pop();
        vec.push_back(u);
        for(auto v:g[u]){
            if(vis[v]==1)continue;
            vis[v]=1; q.push(v); dis[v]=dis[u]+1;
        }
    }
    int bst=0,mx=0;
    for(auto x:vec) {
        if(dis[x]>=mx) {
            mx=dis[x]; bst=x;
        }
    }
    return bst;
}

pair<int,int> getD(int src) {
    bool v[N]={0}; int pre[N]={0},d[N]={0};
    vector<int> vec;
    queue<int> q; q.push(src); v[src]=1;
    while(q.size()){
        int u=q.front(); q.pop(); vec.push_back(u);
        //printf("d[%d]=%d\n", u,d[u]);
        for(auto x:g[u]){
            if(v[x]==1)continue;
            v[x]=1; q.push(x); d[x]=d[u]+1;
            pre[x]=u;
        }
    }
    int len=0,bst=0;
    for(auto i: vec){
        if(d[i]>=len) {
            len=d[i]; bst=i;
        }
    }
    int now=bst;
    while(d[now]>len/2) now=pre[now];
    return make_pair(len,now);
}

vector< pair<int,int> > vec;
pair<int,int> ans[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v); g[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0) {
            int rt = bfs(i);
            pair<int,int> p = getD(rt);
            vec.push_back(p);
        }
    }
    sort(vec.begin(),vec.end());
    int mx=vec[(int)vec.size()-1].first;

    if(vec.size()>=2) {
        for(int i=0;i<vec.size()-1;i++){
            for(int j=i+1;j<vec.size()-1;j++){
                mx=max(mx, (vec[i].first+1)/2 + (vec[j].first+1)/2 + 2);
            }
        }
        for(int i=0;i<vec.size()-1;i++){
            mx = max(mx,(vec[i].first+1)/2 + (vec[vec.size()-1].first+1)/2 + 1);
        }
    }
    printf("%d\n", mx);
    for(int i=0;i<(int)vec.size()-1;i++)
        printf("%d %d\n", vec[i].second,vec[(int)vec.size()-1].second);
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int N = 1002;
int n,m,vis[N],dis[N];

vector<int> g[N];

int bfs(int u){
    queue<int> q; q.push(u); vis[u]=1;
    vector<int> vec;
    while(q.size()){
        int u=q.front(); q.pop();
        vec.push_back(u);
        for(auto v:g[u]){
            if(vis[v]==1)continue;
            vis[v]=1; q.push(v); dis[v]=dis[u]+1;
        }
    }
    int bst=0,mx=0;
    for(auto x:vec) {
        if(dis[x]>=mx) {
            mx=dis[x]; bst=x;
        }
    }
    return bst;
}

pair<int,int> getD(int src) {
    bool v[N]={0}; int pre[N]={0},d[N]={0};
    vector<int> vec;
    queue<int> q; q.push(src); v[src]=1;
    while(q.size()){
        int u=q.front(); q.pop(); vec.push_back(u);
        for(auto x:g[u]){
            if(v[x]==1)continue;
            v[x]=1; q.push(x); d[x]=d[u]+1;
            pre[x]=u;
        }
    }
    int len=0,bst=0;
    for(auto i: vec){
        if(d[i]>=len) {
            len=d[i]; bst=i;
        }
    }
    int now=bst;
    while(d[now]>len/2) now=pre[now];
    return make_pair(len,now);
}

vector< pair<int,int> > vec;
pair<int,int> ans[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v); g[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0) {
            int rt = bfs(i);
            pair<int,int> p = getD(rt);
            p.first = (p.first + 1) / 2;
            vec.push_back(p);
            //printf("(%d, %d)\n", p.first, p.second);
        }
    }
    sort(vec.begin(),vec.end());
    int L=501,R=500;
    for(int i=vec.size()-1;i>=0;i--) {
        if(i%2==0) ans[--L]=vec[i];
        else ans[++R]=vec[i];
    }
    int mx=0;
    for(int i=L;i<=R;i++)for(int j=i;j<=R;j++){
        mx = max(mx, ans[i].first + ans[j].first + j-i);
    }
    printf("%d\n", mx);
    for(int i=L;i<R;i++) {
        printf("%d %d\n", ans[i].second, ans[i+1].second);
    }
}


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1002;
int n,m,vis[N],dis[N];

vector<int> g[N];

int bfs(int u){
    queue<int> q; q.push(u); vis[u]=1;
    vector<int> vec;
    while(q.size()){
        int u=q.front(); q.pop();
        vec.push_back(u);
        for(auto v:g[u]){
            if(vis[v]==1)continue;
            vis[v]=1; q.push(v); dis[v]=dis[u]+1;
        }
    }
    int bst=0,mx=0;
    for(auto x:vec) {
        if(dis[x]>=mx) {
            mx=dis[x]; bst=x;
        }
    }
    return bst;
}

pair<int,int> getD(int src) {
    bool v[N]={0}; int pre[N]={0},d[N]={0};
    vector<int> vec;
    queue<int> q; q.push(src); v[src]=1;
    while(q.size()){
        int u=q.front(); q.pop(); vec.push_back(u);
        for(auto x:g[u]){
            if(v[x]==1)continue;
            v[x]=1; q.push(x); d[x]=d[u]+1;
            pre[x]=u;
        }
    }
    int len=0,bst=0;
    for(auto i: vec){
        if(d[i]>=len) {
            len=d[i]; bst=i;
        }
    }
    int now=bst;
    while(d[now]>len/2) now=pre[now];
    return make_pair(len,now);
}

vector< pair<int,int> > vec;
pair<int,int> ans[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v); g[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0) {
            int rt = bfs(i);
            pair<int,int> p = getD(rt);
            p.first = (p.first + 1) / 2;
            vec.push_back(p);
            //printf("(%d, %d)\n", p.first, p.second);
        }
    }
    sort(vec.begin(),vec.end());
    int L=501,R=500;
    for(int i=vec.size()-1;i>=0;i--) {
        if(i%2==0) ans[--L]=vec[i];
        else ans[++R]=vec[i];
    }
    int mx=0;
    for(int i=L;i<=R;i++)for(int j=i;j<=R;j++){
        mx = max(mx, ans[i].first + ans[j].first + j-i);
    }
    printf("%d\n", mx);
    for(int i=L;i<R;i++) {
        printf("%d %d\n", ans[i].second, ans[i+1].second);
    }
}


#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1002;
int n,m,vis[N],dis[N];

vector<int> g[N];

int bfs(int u){
    queue<int> q; q.push(u); vis[u]=1;
    vector<int> vec;
    while(q.size()){
        int u=q.front(); q.pop();
        vec.push_back(u);
        for(auto v:g[u]){
            if(vis[v]==1)continue;
            vis[v]=1; q.push(v); dis[v]=dis[u]+1;
        }
    }
    int bst=0,mx=0;
    for(auto x:vec) {
        if(dis[x]>=mx) {
            mx=dis[x]; bst=x;
        }
    }
    return bst;
}

pair<int,int> getD(int src) {
    bool v[N]={0}; int pre[N]={0},d[N]={0};
    vector<int> vec;
    queue<int> q; q.push(src); v[src]=1;
    while(q.size()){
        int u=q.front(); q.pop(); vec.push_back(u);
        //printf("d[%d]=%d\n", u,d[u]);
        for(auto x:g[u]){
            if(v[x]==1)continue;
            v[x]=1; q.push(x); d[x]=d[u]+1;
            pre[x]=u;
        }
    }
    int len=0,bst=0;
    for(auto i: vec){
        if(d[i]>=len) {
            len=d[i]; bst=i;
        }
    }
    int now=bst;
    while(d[now]>len/2) now=pre[now];
    return make_pair(len,now);
}

vector< pair<int,int> > vec;
pair<int,int> ans[N];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int u,v; scanf("%d%d",&u,&v);
        g[u].push_back(v); g[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0) {
            int rt = bfs(i);
            pair<int,int> p = getD(rt);
            vec.push_back(p);
        }
    }
    sort(vec.begin(),vec.end());
    int mx=vec[0].first;;

    if(vec.size()>=2) {
        for(int i=0;i<vec.size()-1;i++){
            for(int j=i+1;j<vec.size()-1;j++){
                mx=max(mx, (vec[i].first+1)/2 + (vec[j].first+1)/2 + 2);
            }
        }
        for(int i=0;i<vec.size()-1;i++){
            mx = max(mx,(vec[i].first+1)/2 + (vec[vec.size()-1].first+1)/2 + 1);
        }
    }
    printf("%d\n", mx);
    for(int i=0;i<(int)vec.size()-1;i++)
        printf("%d %d\n", vec[i].second,vec[(int)vec.size()-1].second);
}


#include <iostream>
#include <algorithm>
using namespace std;
const int N = 200000+10;
int n,a[N];
int stk[N],top=0;

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        if(top==0) {
            stk[++top]=a[i];
        } else {
            if(stk[top]==a[i]) top--;
            else {
                if(a[i]>stk[top]) return !printf("NO\n");
                stk[++top]=a[i];
            }
        }
    }
    if(top==1){
        if(stk[top]==*max_element(a+1,a+1+n)) printf("YES\n");
        else printf("NO\n");
        return 0;
    }
    if(top>=2) printf("NO\n");
    else printf("YES\n");
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int bfs (int start_v, vector<vector<int>> &g, vector<int> &dist) {
    queue<int> que;
    que.push(start_v);
    dist[start_v] = 1;
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int to : g[v]) {
            if (dist[to] == 0) {
                que.push(to);
                dist[to] = dist[v] + 1;
            }
        }
    }
    sort(dist.begin(), dist.end());
    reverse(dist.begin(), dist.end());
    if (start_v == 99) {
        for (int i : dist) {
            cout << i << ' ';
        }
        cout << endl;
    }
    return dist[0] + dist[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to]) {
                    r[to] = max(r[to], r[center[i]] + 1);
                }
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
    if (n == 100 && m == 98) {
        cout << r[57] << ' ' << r[99] << endl;
    }
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<vector<int>> dist(col, vector<int> (n, 0));
    int D = 0;
    if (n == 100 && m == 98 && bfs(99, g, dist[1]) == 21) {
        cout << "--" << endl;
    }
    for (int i = 0; i < col; i++) {
        D = max(D, bfs(center[i], g, dist[i]));
        if (D == 22) {
            cout << i;
            return 0;
        }
    }
//    assert(D != 22);
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int dfs2 (int start_v, int v, vector<vector<int>> &g, vector<int> &dist) {
    if (v == start_v) {
        dist[v] = 1;
    }
    for (int to : g[v]) {
        if (!dist[to]) {
            dist[to] = dist[v] + 1;
            dfs2(start_v, to, g, dist);
        }
    }
    for (int to : g[v]) {
        dist[v] = max(dist[v], dist[to]);
    }
    if (v != start_v) {
        return 0;
    }
    vector<int> vv; for (int to : g[v]) {
        vv.push_back(dist[to]);
    }
    sort(vv.begin(), vv.end());
    reverse(vv.begin(), vv.end());
    if (vv.size() == 0) {
        return 0;
    }
    if (vv.size() == 1) {
        return vv[0] - 1;
    }
    return vv[0] + vv[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to]) {
                    r[to] = max(r[to], r[center[i]] + 1);
                }
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
//    for (int i : center) {
//        cout << i << ' ';
//    }
//    cout << endl;
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<vector<int>> dist(col, vector<int> (n, 0));
    int D = 0;
    for (int i = 0; i < col; i++) {
        D = max(D, dfs2(center[i], center[i], g, dist[i]));
        if (D == 32) {
            cout << "D = " << 32 << ", i = " << i << endl;
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int bfs (int start_v, vector<vector<int>> &g, vector<int> &dist) {
    queue<int> que;
    que.push(start_v);
    dist[start_v] = 1;
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int to : g[v]) {
            if (dist[to] == 0) {
                que.push(to);
                dist[to] = dist[v] + 1;
            }
        }
    }
    sort(dist.begin(), dist.end());
    reverse(dist.begin(), dist.end());
    return dist[0] + dist[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
        }
    }
    for (int i = 0; i < col; i++) {
        while (!leaf[i].empty()) {
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                if (!deleted[to]) {
                    r[to] = r[center[i]] + 1;
                    leaf[i].push(to);
                }
            }
            deleted[center[i]] = 1;
        }
    }
//    for (int i : center) {
//        cout << i << ' ';
//    }
//    cout << endl;
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<int> dist(n, 0);
    int D = 0;
    for (int i = 0; i < col; i++) {
        D = max(D, bfs(center[i], g, dist));
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int bfs (int start_v, vector<vector<int>> &g, vector<int> &dist) {
    queue<int> que;
    que.push(start_v);
    dist[start_v] = 1;
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int to : g[v]) {
            if (dist[to] == 0) {
                que.push(to);
                dist[to] = dist[v] + 1;
            }
        }
    }
    sort(dist.begin(), dist.end());
    reverse(dist.begin(), dist.end());
    return dist[0] + dist[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to]) {
                    r[to] = max(r[to], r[center[i]] + 1);
                }
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<vector<int>> dist(col, vector<int> (n, 0));
    int D = 0;
    if (bfs(99, g, dist[1]) == 21) {
        cout << "--" << endl;
    }
    for (int i = 0; i < col; i++) {
        D = max(D, bfs(center[i], g, dist[i]));
        if (D == 22) {
            cout << i;
            return 0;
        }
    }
//    assert(D != 22);
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int dfs2 (int start_v, int v, vector<vector<int>> &g, vector<int> &dist, vector<int> &max_path) {
    if (v == start_v) {
        dist[v] = 1;
    }
    max_path[v] = dist[v];
    for (int to : g[v]) {
        if (!dist[to]) {
            dist[to] = dist[v] + 1;
            dfs2(start_v, to, g, dist, max_path);
        }
    }
    for (int to : g[v]) {
        max_path[v] = max(max_path[v], max_path[to]);
    }
    if (v != start_v) {
        return 0;
    }
    vector<int> vv;
    for (int to : g[v]) {
        vv.push_back(max_path[to]);
    }
    sort(vv.begin(), vv.end());
    reverse(vv.begin(), vv.end());
    if (vv.size() == 0) {
        return 0;
    }
    if (vv.size() == 1) {
        if (start_v == 206) {
            cout << "vv.size() = 1" << endl;
        }
        return vv[0] - 1;
    }
    return vv[0] + vv[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to]) {
                    r[to] = max(r[to], r[center[i]] + 1);
                }
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
//    for (int i : center) {
//        cout << i << ' ';
//    }
//    cout << endl;
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<vector<int>> dist(col, vector<int> (n, 0));
    vector<int> max_path(n, 0);
    int D = 0;
    for (int i = 0; i < col; i++) {
        D = max(D, dfs2(center[i], center[i], g, dist[i], max_path));
        if (D == 32) {
            cout << "main_tree = " << main_tree << endl;
            cout << "D = " << 32 << ", i = " << i << endl;
            return 0;
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int bfs (int start_v, vector<vector<int>> &g, vector<int> &dist) {
    queue<int> que;
    que.push(start_v);
    dist[start_v] = 1;
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int to : g[v]) {
            if (dist[to] == 0) {
                que.push(to);
                dist[to] = dist[v] + 1;
            }
        }
    }
    sort(dist.begin(), dist.end());
    reverse(dist.begin(), dist.end());
    return dist[0] + dist[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
//            cout << "v = " << center[i] << endl;
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    r[to] = r[center[i]] + 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
//    for (int i : center) {
//        cout << i << ' ';
//    }
//    cout << endl;
//    for (int i : r) {
//        cout << i << ' ';
//    }
//    cout << endl;
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }

    vector<int> dist(n, 0);
    int D = 0;
    for (int i = 0; i < col; i++) {
        D = max(D, bfs(center[i], g, dist));
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}


//Author: Tanya Cheremkhina

#include <bits/stdc++.h>

using namespace std;

#ifdef DEBUG
    ifstream fin("input.txt");
    ofstream fout("output.txt");
    #define cin fin
    #define cout fout
#endif //DEBUG

void dfs1 (int v, vector<vector<int>> &g, vector<int> &used, int col) {
    used[v] = col;
    for (int to : g[v]) {
        if (!used[to]) {
            dfs1(to, g, used, col);
        }
    }
}

int bfs (int start_v, vector<vector<int>> &g, vector<int> &dist) {
    queue<int> que;
    que.push(start_v);
    dist[start_v] = 1;
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int to : g[v]) {
            if (dist[to] == 0) {
                que.push(to);
                dist[to] = dist[v] + 1;
            }
        }
    }
    sort(dist.begin(), dist.end());
    reverse(dist.begin(), dist.end());
    if (start_v == 57) {
        for (int i : dist) {
            cout << i << ' ';
        }
        cout << endl;
    }
    return dist[0] + dist[1] - 2;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> p(n, 0), used(n, 0);;
    for (int i = 0; i < m; i++) {
        int u, v; cin >> u >> v; u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
        p[v]++;
        p[u]++;
    }
    int col = 1;
    for (int i = 0; i < n; i++) {
        if (!used[i]) {
            dfs1(i, g, used, col);
            col++;
        }
    }
    for (int &i : used) {
        i--;
    }
    col--;
    vector<int> center(col, -1), r(n, 0);
    vector<queue<int>> leaf(col);
    vector<int> deleted(n, 0);
    for (int i = 0; i < n; i++) {
        if (p[i] <= 1) {
            leaf[used[i]].push(i);
            deleted[i] = 1;
        }
    }
    for (int i = 0; i < col; i++) {
        int k = 0;
        while (!leaf[i].empty()) {
            k++;
            center[i] = leaf[i].front();
            leaf[i].pop();
            for (int to : g[center[i]]) {
                p[to]--;
                if (!deleted[to]) {
                    r[to] = max(r[to], r[center[i]] + 1);
                }
                if (!deleted[to] && p[to] <= 1) {
                    deleted[to] = 1;
                    leaf[i].push(to);
                }
            }
        }
        if (r[center[i]] == 0 && k > 1) {
            r[center[i]] = 1;
        }
    }
    if (n == 100 && m == 98) {
        cout << r[57] << ' ' << r[99] << endl;
    }
    int main_tree = 0;
    for (int i = 0; i < col; i++) {
        if (r[center[i]] > r[center[main_tree]]) {
            main_tree = i;
        }
    }
    vector<vector<int>> dist(col, vector<int> (n, 0));
    int D = 0;
    if (n == 100 && m == 98 && bfs(99, g, dist[1]) == 21) {
        cout << "--" << endl;
    }
    for (int i = 0; i < col; i++) {
        D = max(D, bfs(center[i], g, dist[i]));
        if (D == 22) {
            cout << i;
            return 0;
        }
    }
//    assert(D != 22);
    vector<pair<int, int>> ans;
    for (int i = 0; i < col; i++) {
        if (i != main_tree) {
            D = max(D, r[center[i]] + r[center[main_tree]] + 1);
            ans.emplace_back(center[i] + 1, center[main_tree] + 1);
        }
    }
    vector<int> R(col);
    for (int i = 0; i < col; i++) {
        R[i] = r[center[i]];
    }
    sort(R.begin(), R.end());
    reverse(R.begin(), R.end());
    if (R.size() > 2) {
        D = max(D, R[1] + R[2] + 2);
    }
    cout << D << '\n';
    for (auto i : ans) {
        cout << i.first << ' ' << i.second << '\n';
    }
    return 0;
}