
import scala.annotation.tailrec
import scala.io.StdIn
import scala.collection.mutable

object Main extends App {
  val Array(n,m,_*) = StdIn.readLine().split(' ').map(_.toInt)
  val roads = for(i <- 1 to m)yield{
    val Array(a,b,_*) = StdIn.readLine().split(' ').map(_.toInt)
    (a,b)
  }
/*  var eMap = mutable.Map.empty[Int,mutable.Map[Int,Boolean]].withDefault(_=>mutable.Map.empty.withDefaultValue(false))
  for((a,b) <- roads){
    eMap(a)(b) = true
    eMap(b)(a) = true
  }*/

  val eMap = roads.foldLeft(Map.empty[Int,Map[Int,Boolean]].withDefault(_=>Map.empty[Int,Boolean].withDefaultValue(false)))
    {case (map,(a,b)) => {
        val m1 = map.updated(a,map(a).updated(b,true))
        val m2 = m1.updated(b,map(b).updated(a,true))
        m2
      }
    }

  val verts = mutable.Set.range(1,n+1)
  var classes = 0
  while(!verts.isEmpty){
    val graph = new Graph[Int](verts.toSet,eMap)
    verts --= graph.adjacentClass(verts.head)
    classes += 1
  }

  println(classes - 1 )

}

class Graph[V](val vertices:Set[V] , val edgeMap:Map[V,Map[V,Boolean]]){
  val closures :Map[V,Set[V]]= vertices.map(v => v -> closure(v)).toMap
  def isAdjacent(v1:V,v2:V):Boolean = edgeMap(v1)(v2)
  def closure(v:V):Set[V] = vertices.filter(ve => edgeMap(v)(ve) || edgeMap(ve)(v))
  def adjacentClass(v:V):Set[V]={
    val memo = mutable.Set.empty[V]
    def search(vert:V):Unit={
      memo += vert
      closures(vert).filter(!memo(_)).foreach(search)
    }
    search(v)
    memo.toSet
  }
}




