Problem:
Score : 400 points

Problem Statement

There are N persons called Person 1 through Person N.

You are given M facts that "Person A_i and Person B_i are friends." The same fact may be given multiple times.

If X and Y are friends, and Y and Z are friends, then X and Z are also friends. There is no friendship that cannot be derived from the M given facts.

Takahashi the evil wants to divide the N persons into some number of groups so that every person has no friend in his/her group.

At least how many groups does he need to make?

Constraints

2 \leq N \leq 2\times 10^5

0 \leq M \leq 2\times 10^5

1\leq A_i,B_i\leq N

A_i \neq B_i

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
\vdots
A_M B_M

Output

Print the answer.

Sample Input 1

5 3
1 2
3 4
5 1

Sample Output 1

3

Dividing them into three groups such as \{1,3\}, \{2,4\}, and \{5\} achieves the goal.

Sample Input 2

4 10
1 2
2 1
1 2
2 1
1 2
1 3
1 4
2 3
2 4
3 4

Sample Output 2

4

Sample Input 3

10 4
3 1
4 1
5 9
2 6

Sample Output 3

3

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <bits/stdc++.h>

typedef uint64_t u64;
typedef int64_t i64;
typedef uint32_t u32;
typedef int32_t i32;
typedef uint16_t u16;
typedef int16_t i16;
typedef uint8_t u8;
typedef int8_t i8;

using namespace std;

#define rep(idx, N) for (u64 idx = 0; idx < N; idx++)

class UnionFind {
public:
  vector<i32> r; // 親なら頂点数*-1, それ以外なら自分の親
  UnionFind(i32 N) : r(N, -1) {}
  i32 root(i32 x) {
    if (r[x] < 0)
      return x;
    else {
      r[x] = root(r[x]);
      return root(r[x]);
    }
  }
  bool unite(i32 x, i32 y) {
    i32 rx = root(x);
    i32 ry = root(y);
    if (rx == ry)
      return false;

    if (r[rx] > r[ry])
      swap(rx, ry);

    r[rx] = r[rx] + r[ry];
    r[ry] = rx;

    return true;
  }
  bool same(i32 x, i32 y) {
    if (root(x) == root(y))
      return true;
    else
      return false;
  }
  i32 size(i32 x) { return -r[root(x)]; }
};

int main() {
  u32 n, m;
  cin >> n >> m;

  UnionFind UF(n);

  unordered_set<u32> p;
  rep(i, n) { p.insert(i); }

  rep(i, m) {
    u32 a, b;
    cin >> a >> b;
    UF.unite(a - 1, b - 1);
  }

  i32 ans = 0;

  rep(i, n) { ans = max({ans, UF.size(i)}); }

  cout << ans;

  return 0;
}