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# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

using System;
using static System.Console;
using static System.Math;
using System.Numerics;
using System.Collections.Generic;
using System.Linq;


namespace AtCoder
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var s = myRead.readIntArray();
            UnionFind u = new UnionFind(s[0]);
            for (int i = 0; i < s[1]; i++)
            {
                var t = myRead.readIntArray().Select(x => x - 1).ToArray();
                u.Add(t[0], t[1]);
            }

            WriteLine(u.max);

        }
    }
    public static class myRead
    {
        public static int readInt() { return int.Parse(ReadLine()); }
        public static long readLong() { return long.Parse(ReadLine()); }
        public static string readStr() { return ReadLine(); }
        public static int[] readIntArray() { return ReadLine().Split(' ').Select(int.Parse).ToArray(); }
        public static long[] readLongArray() { return ReadLine().Split(' ').Select(long.Parse).ToArray(); }
        public static string[] readStrArray() { return ReadLine().Split(' '); }
    }


    public class UnionFind
    {
        public int[] par;
        public int[] size;
        public int max;
        public UnionFind(int n)
        {
            par = new int[n];
            size = new int[n].Select(x => 1).ToArray();
            for (int i = 0; i < n; i++)
                par[i] = i;     //初期値は配列の番号

        }

        public int FindPar(int a)
        {
            return par[a] == a ? a : FindPar(par[a]); //親が自身と等しくなるまで繰り返す
        }

        public void Add(int a, int b)
        {
            int aPar = FindPar(a);
            int bPar = FindPar(b);
            if (aPar == bPar)
                return;         //親が同じなら何もしない
            else if (aPar < bPar)   //親が小さい方に入れる
            {
                par[b] = aPar;
                size[aPar] += size[bPar];
                max = size[aPar] > max ? size[aPar] : max;
            }
            else
            {
                par[a] = bPar;
                size[bPar] += size[aPar];
                max = size[bPar] > max ? size[bPar] : max;
            }
        }

        public bool CheckPar(int a, int b) //同じ木の中にいるかどうか
        {
            return FindPar(a) == FindPar(b);
        }
    }

}