Problem:
Score : 300 points

Problem Statement

There are N cities numbered 1 through N, and M bidirectional roads numbered 1 through M.
Road i connects City A_i and City B_i.

Snuke can perform the following operation zero or more times:

Choose two distinct cities that are not directly connected by a road, and build a new road between the two cities.

After he finishes the operations, it must be possible to travel from any city to any other cities by following roads (possibly multiple times).

What is the minimum number of roads he must build to achieve the goal?

Constraints

2 \leq N \leq 100,000

1 \leq M \leq 100,000

1 \leq A_i < B_i \leq N

No two roads connect the same pair of cities.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
:
A_M B_M

Output

Print the answer.

Sample Input 1

3 1
1 2

Sample Output 1

1

Initially, there are three cities, and there is a road between City 1 and City 2.

Snuke can achieve the goal by building one new road, for example, between City 1 and City 3.
After that,

We can travel between 1 and 2 directly.

We can travel between 1 and 3 directly.

We can travel between 2 and 3 by following both roads (2 - 1 - 3).

Solution in Kotlin (1.3.71) (judge verdict: Accepted)

import java.math.*
import java.util.*
import java.util.function.*
import java.util.stream.*
import kotlin.math.min

fun main(args: Array<String>) {
  val sc = Scanner(System.`in`)
  val n = sc.nextInt()
  val m = sc.nextInt()
  val list = (0 until n).map {
    UnionFind(it)
  }
  (0 until m).forEach {
    val a = sc.nextInt() - 1
    val b = sc.nextInt() - 1
    UnionFind.union(list[a], list[b], ::min)
  }
  println(list.map(UnionFind<Int>::getGroupValue).toSet().size - 1);
}

/**
 * Union Find
 * @param <T> 値の型
</T> */
internal class UnionFind<T>(
  /** 値  */
  val value: T
) {
  /** 親 (なければnull)  */
  private var parent: UnionFind<T>? = null
  /**
   * この要素の値を返す。
   * @return 値
   */

  /** 所属するグループの合算した値 (root要素以外のgroupValueは正しいとは限らない)  */
  private var groupValue: T
  override fun equals(o: Any?): Boolean {
    return this === o
  }

  /**
   * root要素を返す。
   * @return root要素
   */
  private val root: UnionFind<T>
    private get() {
      if (parent == null) {
        return this
      }
      val root = parent!!.root
      parent = root
      return root
    }

  /**
   * この要素が属するグループの値を返す。
   * @return グループの値
   */
  fun getGroupValue(): T {
    return root.groupValue
  }

  companion object {
    /**
     * 同じグループに属するかどうか
     * @param a a
     * @param b b
     * @param <S> 値の型
     * @return 同じグループに属するならtrue
    </S> */
    fun <S> sameGroup(a: UnionFind<S>, b: UnionFind<S>): Boolean {
      return a.root == b.root
    }

    /**
     * 同じ木に所属させる
     * @param a a
     * @param b b
     * @param <S> 値の型
    </S> */
    fun <S> union(a: UnionFind<S>, b: UnionFind<S>) {
      union(a, b, { _1, _ -> _1 })
    }

    /**
     * 同じ木に所属させる。また、値の計算もする
     * @param a a
     * @param b b
     * @param groupValueFunction aとbが異なるグループに属するとき、その2つのグループの値を合算する関数。
     * @param <S> 値の型
    </S> */
    fun <S> union(a: UnionFind<S>, b: UnionFind<S>, groupValueFunction: (S, S) -> S) {
      val aRoot = a.root
      val bRoot = b.root
      if (aRoot != bRoot) {
        bRoot.parent = aRoot
        aRoot.groupValue = groupValueFunction(aRoot.groupValue, bRoot.groupValue)
      }
    }
  }

  /**
   * Union Find
   * @param value 値
   */
  init {
    groupValue = value
  }
}