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 Rust (1.42.0) (judge verdict: Accepted)

// EbTech's Rust template. Thanks EbTech!
#![allow(unused_imports)]
use std::cmp::{max, min, Reverse};
use std::collections::{HashMap, HashSet};
use std::io::{self, prelude::*};
use std::str;

/*
5 2
5 -4 4 3 -5
4 3
3 -1

5 -4 4 3 -5 -> 8
5 -4 4 3 3  -> 11
5 -4 4 -1 3 -> 7
*/

struct Scanner<R> {
    reader: R,
    buf_str: Vec<u8>,
    buf_iter: str::SplitWhitespace<'static>,
}
impl<R: BufRead> Scanner<R> {
    fn new(reader: R) -> Self {
        Self {
            reader,
            buf_str: vec![],
            buf_iter: "".split_whitespace(),
        }
    }
    fn next<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buf_iter.next() {
                return token.parse().ok().expect("Failed parse");
            }
            self.buf_str.clear();
            self.reader
                .read_until(b'\n', &mut self.buf_str)
                .expect("Failed read");
            self.buf_iter = unsafe {
                let slice = str::from_utf8_unchecked(&self.buf_str);
                std::mem::transmute(slice.split_whitespace())
            }
        }
    }
}

fn solve<R: BufRead, W: Write>(scan: &mut Scanner<R>, w: &mut W) {
    let n: usize = scan.next();
    let m: usize = scan.next();
    let mut al = vec!(vec!();n);
    for _ in 0..m {
        let u: usize = scan.next();
        let v: usize = scan.next();
        al[u-1].push(v-1);
        al[v-1].push(u-1);
    }
    fn dfs (u: usize, al: & Vec<Vec<usize>>, vis: &mut Vec<bool>) -> usize {
        let mut count = 1;
        if vis[u] {
            return 0;
        }
        vis[u] = true;
        for v in &al[u] {
            count += dfs (*v, al, vis);
        }
        count
    }
    let mut vis = vec![false;n];
    let mut res = 0;
    for i in 0..n {
        if vis[i] {
            continue}
        res = max(res, dfs (i, &al, &mut vis));
    }
    writeln!(w, "{}", res);
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());
    // let t: u64 = scan.next();
    let t = 1;
    for _ in 0..t {
        solve(&mut scan, &mut out);
    }
}