from collections import deque



n, m = list(map(int, input().split()))

ab_array = [list(map(int, input().split())) for _ in range(m)]



ad_sum_array = [0] * n

ad_array = [set() for _ in range(n)]



for ab in ab_array:

    a, b = ab

    ad_array[a - 1].add(b - 1)

    ad_array[b - 1].add(a - 1)



check_array = [False] * n



def bfs(node_num):

    queue = deque([node_num])

    check_array[node_num] = True

    num = 1



    while queue:

        node = queue.popleft()

        for ad in ad_array[node]:

            if not check_array[ad]:

                check_array[ad] = True

                queue.append(ad)

                num += 1

    return num



ans = 0

for i in range(n):

    if not check_array[i]:

        ans = max(ans, bfs(i))



print(ans)
class union_find:

    def __init__(self, node_num):

        self.root_array = [-1] * node_num



    def root(self, x):

        if self.root_array[x] < 0:

            return x

        else:

            self.root_array[x] = self.root(self.root_array[x])

            return self.root_array[x]



    def unite(self, x, y):

        x = self.root(x)

        y = self.root(y)

        if x == y:

            return

        if self.root_array[x] > self.root_array[y]:

            x, y = y, x

        self.root_array[x] += self.root_array[y]

        self.root_array[y] = x



    def size(self, x):

        return -self.root_array[self.root(x)]





def solve(n, m, ab_array):

    uf = union_find(n)

    for ab in ab_array:

        a, b = ab

        uf.unite(a - 1, b - 1)



    ans = 0

    for i in range(n):

        ans = max(ans, uf.size(i))



    return ans



if __name__ == '__main__':

    n, m = list(map(int, input().split()))

    ab_array = [list(map(int, input().split())) for _ in range(m)]

    ans = solve(n, m, ab_array)

    print(ans)
from collections import deque

n, m = list(map(int, input().split()))
ab_array = [list(map(int, input().split())) for _ in range(m)]
ad_sum_array = [0] * n
ad_array = [set() for _ in range(n)]
for ab in ab_array:
    a, b = ab
    ad_array[a - 1].add(b - 1)
    ad_array[b - 1].add(a - 1)
check_array = [False] * n


def bfs(node_num):
    queue = deque([node_num])
    check_array[node_num] = True
    num = 1
    while queue:
        node = queue.popleft()
        for ad in ad_array[node]:
            if not check_array[ad]:
                check_array[ad] = True
                queue.append(ad)
                num += 1
    return num


ans = 0
for i in range(n):
    if not check_array[i]:
        ans = max(ans, bfs(i))
print(ans)

class union_find:
    def __init__(self, node_num):
        self.root_array = [-1] * node_num

    def root(self, x):
        if self.root_array[x] < 0:
            return x
        else:
            self.root_array[x] = self.root(self.root_array[x])
            return self.root_array[x]

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        if self.root_array[x] > self.root_array[y]:
            x, y = y, x
        self.root_array[x] += self.root_array[y]
        self.root_array[y] = x

    def size(self, x):
        return -self.root_array[self.root(x)]


def solve(n, m, ab_array):
    uf = union_find(n)
    for ab in ab_array:
        a, b = ab
        uf.unite(a - 1, b - 1)
    ans = 0
    for i in range(n):
        ans = max(ans, uf.size(i))
    return ans


if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    ab_array = [list(map(int, input().split())) for _ in range(m)]
    ans = solve(n, m, ab_array)
    print(ans)

-from collections import deque +class union_find: +    def __init__(self, node_num): +        self.root_array = [-1] * node_num -n, m = list(map(int, input().split())) -ab_array = [list(map(int, input().split())) for _ in range(m)] -ad_sum_array = [0] * n -ad_array = [set() for _ in range(n)] -for ab in ab_array: -    a, b = ab -    ad_array[a - 1].add(b - 1) -    ad_array[b - 1].add(a - 1) -check_array = [False] * n +    def root(self, x): +        if self.root_array[x] < 0: +            return x +        else: +            self.root_array[x] = self.root(self.root_array[x]) +            return self.root_array[x] + +    def unite(self, x, y): +        x = self.root(x) +        y = self.root(y) +        if x == y: +            return +        if self.root_array[x] > self.root_array[y]: +            x, y = y, x +        self.root_array[x] += self.root_array[y] +        self.root_array[y] = x + +    def size(self, x): +        return -self.root_array[self.root(x)] -def bfs(node_num): -    queue = deque([node_num]) -    check_array[node_num] = True -    num = 1 -    while queue: -        node = queue.popleft() -        for ad in ad_array[node]: -            if not check_array[ad]: -                check_array[ad] = True -                queue.append(ad) -                num += 1 -    return num +def solve(n, m, ab_array): +    uf = union_find(n) +    for ab in ab_array: +        a, b = ab +        uf.unite(a - 1, b - 1) +    ans = 0 +    for i in range(n): +        ans = max(ans, uf.size(i)) +    return ans -ans = 0 -for i in range(n): -    if not check_array[i]: -        ans = max(ans, bfs(i)) -print(ans) +if __name__ == "__main__": +    n, m = list(map(int, input().split())) +    ab_array = [list(map(int, input().split())) for _ in range(m)] +    ans = solve(n, m, ab_array) +    print(ans)