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>
#define _GLIBCXX_DEBUG
using namespace std;
using ll = long long;

#define rep(i,n) for(ll i=0;i<ll(n);i++)
#define YESNO(T) if(T){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}
#define yesno(T) if(T){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}
#define YesNo(T) if(T){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}

const ll INF = 1LL << 60;
const ll MOD = 1e9 + 7;
const double pi = 3.14159265358979;

struct UnionFind {
    vector<ll> d;
    //親(負)…木のsize*(-1)
    //子(正)…親のindex

    UnionFind(ll n){
        d = vector<ll>(n,-1);        
    }
    //初期化

    ll find(ll x){
        if (d[x] < 0) return x;
        return d[x] = find(d[x]);
    }
    //親のindexを返す

    bool unite(ll x,ll y){
        x = find(x);
        y = find(y);

        if (x == y) return false;

        if (d[x] >d[y]) swap(x,y);

        d[x] += d[y];
        d[y] = x;

        return true;
    }
    //木と木を接続する

    bool same(ll x,ll y){
        return find(x) == find(y) ? true : false;
    }
    //xとyの親が同じか判定する

    ll size(ll x){
        return -d[find(x)];
    }
    //xが属する木のsizeを返す
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    ll n,m;
    cin >> n >> m;

    UnionFind uf(n);

    rep(i,m){
        ll a,b;
        cin >> a >> b;
        a--;b--;

        uf.unite(a,b);
    }

    ll ans = 0;
    rep(i,n){
        ans = max(ans,uf.size(i));
    }

    cout << ans << endl;


}