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 Python (3.8.2) (judge verdict: Wrong Answer)

import collections  # すごく便利なモジュール
 
 
# 該当する頂点がないことを示す値
INVALID = -1
 
 
# 幅優先探索用クラス
class BreadthFirstSearch(object):
 
    def __init__(self, max_v, max_e, adj_vertices):
        self.max_v = max_v
        self.max_e = max_e
        self.adj_vertices = adj_vertices
        # 各頂点が訪問済みかを記録するdefaultdict
        # 既定の値はFalse
        self.visited = collections.defaultdict(bool)
        # 各頂点のひとつ前に訪問した頂点を記録するdefaultdict
        # 既定の値はINVALID
        self.pred = collections.defaultdict(lambda: INVALID)
 
    # 与えられた頂点から幅優先探索を開始し、
    # それが属する連結成分が木であるか判定する
    def in_tree(self, start_v):
        self.visited[start_v] = True
        # 両端キューをキューとして使う
        q = collections.deque()
        q.append(start_v)
        while q:
            u = q.popleft()
            for v in self.adj_vertices[u]:
                if self.visited[v]:  # 条件1
                    if self.pred[u] != v:  # 条件2
                        return False
                    else:
                        continue
                self.visited[v] = True
                self.pred[v] = u
                q.append(v)
        return True
 
    # すべての頂点を順に調べ、木を数える
    # 未訪問の頂点についてin_treeによる判定を行う
    def count_trees(self):
        counter = 0
        for u in range(self.max_v):
            if self.visited[u]:
                continue
            if self.in_tree(u):
                counter += 1
            else:
                counter += 1
        return counter
 
 
def main():
    # 頂点および辺の最大値
    max_v, max_e = map(int, input().split())
    # 隣接リスト
    adj_vertices = collections.defaultdict(list)
    for _ in range(max_e):
        # 入力は1始まりであるので、これを0始まりに変換する
        u, v = map(lambda x: int(x) - 1, input().split())
        adj_vertices[u].append(v)
        adj_vertices[v].append(u)
    bfs = BreadthFirstSearch(max_v, max_e, adj_vertices)
    print(bfs.count_trees()-1)
 
 
if __name__ == '__main__':
    main()