using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
//using System.Text;
//using System.Text.RegularExpressions;
//using System.Globalization;
//using System.Diagnostics;
using static System.Console;
//using System.Numerics;
//using static System.Math;
//using pair = Pair<int, int>;

class Program
{
    static void Main()
    {
        //SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        new Program().solve();
        Out.Flush();
    }
    Scanner cin = new Scanner();
    readonly int[] dd = { 0, 1, 0, -1, 0 }; //→↓←↑
    readonly int mod = 1000000007;
    void chmax<T>(ref T a, T b) where T : IComparable<T> { a = a.CompareTo(b) < 0 ? b : a; }
    void chmin<T>(ref T a, T b) where T : IComparable<T> { a = a.CompareTo(b) < 0 ? a : b; }

    void solve()
    {
        int N = cin.nextint;
        int M = cin.nextint;

        var G = new List<int>[N];
        for (int i = 0; i < N; i++)
        {
            G[i] = new List<int>();
        }
        var U = new DisjointSet(N);
        for (int i = 0; i < M; i++)
        {
            int a = cin.nextint - 1;
            int b = cin.nextint - 1;
            G[a].Add(b);
            G[b].Add(a);
        }

        int cnt = 0;
        for (int i = 1; i < N; i++)
        {
            bool flag = true;
            foreach (var v in G[i])
            {
                if (U.Same(i - 1, v))
                {
                    flag = false;
                }
            }
            if (flag)
            {
                U.Unite(i, i - 1);
                cnt++;
            }
        }
        WriteLine(N - 1 - cnt);
    }

    class DisjointSet
    {
        int[] par;
        byte[] rank;
        /// <summary>
        /// 0 から <paramref name="N"/>-1 までの番号がついた <paramref name="N"/> 個の要素からなる集合を作成します．
        /// </summary>
        /// <param name="N">要素数</param>
        /// <remarks>このコンストラクタは O(N) で実行されます．</remarks>
        public DisjointSet(int N)
        {
            par = new int[N];
            rank = new byte[N];
            for (int i = 0; i < N; i++)
                par[i] = -1;
        }
        /// <summary>
        /// 指定した要素が属する集合の代表値を取得します．
        /// </summary>
        /// <param name="id">調べたい要素の 0-indexed での番号</param>
        /// <returns>指定した要素が属する集合の代表値</returns>
        /// <remarks>最悪計算量 O(α(N)) で実行されます．</remarks>
        public int this[int id]
        {
            get
            {
                if ((par[id] < 0)) return id;
                return par[id] = this[par[id]];
            }
        }
        /// <summary>
        /// 指定した 2 つの要素が属する集合同士を 1 つに統合することを試みます．
        /// </summary>
        /// <param name="x">最初の要素の 0-indexed での番号</param>
        /// <param name="y">2 つ目の要素の 0-indexed での番号</param>
        /// <returns>統合に成功したならば true，そうでなければ false．</returns>
        /// <remarks>最悪計算量 O(α(N)) で実行されます．</remarks>
        public bool Unite(int x, int y)
        {
            x = this[x]; y = this[y];
            if (x == y) return false;
            if (rank[x] < rank[y]) { var tmp = x; x = y; y = tmp; }
            par[x] += par[y];
            par[y] = x;
            if (rank[x] == rank[y])
                rank[x]++;
            return true;
        }
        /// <summary>
        /// 指定した要素が属する集合のサイズを取得します．
        /// </summary>
        /// <param name="x">指定する要素の 0-indexed での番号</param>
        /// <returns>集合のサイズ</returns>
        /// <remarks>最悪計算量 O(α(N)) で実行されます．</remarks>
        public int Size(int x) { return -par[this[x]]; }

        /// <summary>
        /// 指定した 2 つの要素が属する集合が同じかどうかを判定する．計算量 O(α(N))．
        /// </summary>
        /// <param name="x">最初の要素の 0-indexed での番号</param>
        /// <param name="y">2 つ目の要素の 0-indexed での番号</param>
        /// <returns>同じならば true，そうでなければ false．</returns>
        /// <remarks>最悪計算量 O(α(N)) で実行されます．</remarks>
        public bool Same(int x, int y) { return this[x] == this[y]; }

    }   
}

class Scanner
{
    string[] s; int i;
    char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan { get { return ReadLine().Split(); } }
    public int[] scanint { get { return Array.ConvertAll(scan, int.Parse); } }
    public long[] scanlong { get { return Array.ConvertAll(scan, long.Parse); } }
    public double[] scandouble { get { return Array.ConvertAll(scan, double.Parse); } }
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = ReadLine();
            while (st == "") st = ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint { get { return int.Parse(next); } }
    public long nextlong { get { return long.Parse(next); } }
    public double nextdouble { get { return double.Parse(next); } }
}

Measured memory_bytes: 28688