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: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;

using E = System.Linq.Enumerable;

public class Program
{
    public static void Main()
    {
        var nm = Console.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
        var (n, m) = (nm[0], nm[1]);
        var seqAB = new (int A, int B)[m];
        for (int i = 0; i < seqAB.Length; ++i)
        {
            var ab = Console.ReadLine().Split().Select(x => int.Parse(x)).ToArray();
            seqAB[i] = (ab[0], ab[1]);
        }

        var uf = new UnionFind(n + 1);
        foreach (var (a, b) in seqAB)
        {
            uf.Unite(a, b);
        }

        var clusterIndividual = new HashSet<int>();
        for (int i = 1; i < uf.Count; ++i)
        {
            clusterIndividual.Add(uf.Find(i));
        }

        var max = clusterIndividual.Max(x => uf.GetSize(x));

        Console.WriteLine(max);
    }
}

class UnionFind
{
    int[] nodes;

    public int Count { get; private set; }

    public UnionFind(int size)
    {
        this.nodes = Enumerable.Repeat(-1, size).ToArray();
        Count = size;
    }

    public int Find(int x)
    {
        var p = nodes[x];
        if (p < 0)
        {
            return x;
        }

        return nodes[x] = Find(p);
    }

    public void Unite(int x, int y)
    {
        var p = Find(x);
        var q = Find(y);
        if (p == q)
        {
            return;
        }

        var r = nodes[p];
        var s = nodes[q];
        if (r > s)
        {
            p += q;
            q = p - q;
            p -= q;
        }
        nodes[p] += nodes[q];
        nodes[q] = p;
        Count--;
    }

    public bool Union(int x, int y)
        => Find(x) == Find(y);

    public int GetSize(int x)
        => -nodes[Find(x)];
}