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: Runtime Error)

#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int,int>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
const ll llINF = 1LL << 60;
const int iINF = 1e9;



//---Union Find---
struct UnionFind{
  // グループのサイズ、要素の親idx、要素から親までのランクの配列
  vector<int> gsize,parent,rank;

  //コンストラクタ　各配列を初期化
  UnionFind(int N){
    gsize = vector<int>(N,1);
    parent = vector<int>(N);
    rank = vector<int>(N);
  }

  //親を求める
  int findparent(int x){
    if(parent[x]==0) return x;
    else return parent[x] = findparent(parent[x]); //rankが小さくなるよう親を再設定
  }

  // 2要素x,yの属するグループを合併
  bool unite(int x, int y){
    x = findparent(x);
    y = findparent(y);
    if(x==y) return false;
    
    if(rank[x] < rank[y]){
      parent[x] = y;
      gsize[y] += gsize[x];
      gsize[x] = 0;
    }else{
      parent[y] = x;
      gsize[x] += gsize[y];
      gsize[y] = 0;
      if(rank[x]==rank[y]) rank[x]++;
    }
  }

  // 2要素x,yが同じ集合に属するかどうか
  bool same(int x, int y){
    return findparent(x) == findparent(y);
  }
};


//---main---------------------------------------------
int main(){
    //main
    int N,M;
    cin >> N >> M;

    UnionFind UF(N);

    int Ai,Bi;
    rep(mi,M){
        cin >> Ai >> Bi;
        Ai--; Bi--;
        UF.unite(Ai,Bi);
    }

    int ans = 0;
    for(int gs : UF.gsize) chmax(ans,gs);

    //rep(i,N) cout << UF.gsize[i] << " " << UF.parent[i] << " " << UF.rank[i] << endl;

    cout << ans << endl;

    return 0;
}