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 Java (OpenJDK 11.0.6) (judge verdict: Wrong Answer)

import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    resolve(System.in, System.out);
  }

  static void resolve(InputStream is, PrintStream pw) {
    Scanner sc = new Scanner(is);
    int n = Integer.parseInt(sc.next());
    int m = Integer.parseInt(sc.next());
    Person persons[] = new Person[n + 1];
    List<Group> groups = new ArrayList<>();
    for (int i = 0; i < n + 1; i++) {
      persons[i] = new Person(i);
    }
    for (int i = 0; i < m; i++) {
      int from = Integer.parseInt(sc.next());
      int to = Integer.parseInt(sc.next());
      if (!persons[from].belongsToGroup() && !persons[to].belongsToGroup()) {
        int groupIndex = groups.size();
        Group g = new Group();
        g.memberCount += 2;
        persons[from].groupIndex = groupIndex;
        persons[to].groupIndex = groupIndex;
        groups.add(g);
      } else if (!persons[from].belongsToGroup() && persons[to].belongsToGroup()) {
        Group g = groups.get(persons[to].groupIndex);
        g.memberCount++;
        persons[from].groupIndex = persons[to].groupIndex;
      } else if (persons[from].belongsToGroup() && !persons[to].belongsToGroup()) {
        Group g = groups.get(persons[from].groupIndex);
        g.memberCount++;
        persons[to].groupIndex = persons[from].groupIndex;
      } else {
        Group fromG = groups.get(persons[from].groupIndex);
        Group toG = groups.get(persons[to].groupIndex);
        if (fromG == toG) {
          continue;
        }
        fromG.memberCount += toG.memberCount;
        groups.set(persons[to].groupIndex, fromG);
      }
    }
    pw.println(
      groups.stream().mapToInt(g -> g.memberCount).max().orElse(1)
    );
  }

  static class Group {

    int memberCount;
  }

  static class Person {

    int num;
    int groupIndex = -1;

    Person(int num) {
      this.num = num;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      Person person = (Person) o;
      return num == person.num;
    }

    @Override
    public int hashCode() {
      return Objects.hash(num);
    }

    boolean belongsToGroup() {
      return groupIndex != -1;
    }
  }
}