N,M=list(map(int,input().split()))

f=[set() for i in range(N)]

v=[False]*N

g=[]



for i in range(0,M):

    a,b=list(map(int,input().split()))

    a-=1

    b-=1

    f[a].add(b)

    f[b].add(a)



for i in range(0,N):

    if v[i]:

        continue

    s=set()

    q=[i]

    while len(q)>0:

        p=q.pop()

        v[p]=True

        s.add(p)

        for x in f[p]:

            if v[x]:

                continue

            q.append(x)

    g.append(s)



z=0

for x in g:

    z=max(z,len(x))



print(z)
class UnionFind():



    def __init__(self, n):

        self.parent = [i for i in range(0, n)]

        self.rank= [0] * n



    def root(self, x):

        if self.parent[x] != x:

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

        return self.parent[x]



    def union(self, x, y):

        x = self.root(x)

        y = self.root(y)

        if self.rank[x] < self.rank[y]:

            self.parent[x] = y

        else:

            self.parent[y] = x

            if self.rank[x] == self.rank[y]:

                self.rank[x] += 1



    def same(self, x, y):

        return self.find(x) == self.find(y)



    def rootRank(self, x):

        return self.rank[self.root(x)]



N,M=list(map(int,input().split()))



uf = UnionFind(N)



for i in range(M):

    a,b=list(map(int,input().split()))

    a-=1

    b-=1

    uf.union(a,b)



z=0

c=[0]*N

for i in range(N):

    p=uf.root(i)

    c[p]+=1

    if z<c[p]:

        z=c[p]



print(z)

N, M = list(map(int, input().split()))
f = [set() for i in range(N)]
v = [False] * N
g = []
for i in range(0, M):
    a, b = list(map(int, input().split()))
    a -= 1
    b -= 1
    f[a].add(b)
    f[b].add(a)
for i in range(0, N):
    if v[i]:
        continue
    s = set()
    q = [i]
    while len(q) > 0:
        p = q.pop()
        v[p] = True
        s.add(p)
        for x in f[p]:
            if v[x]:
                continue
            q.append(x)
    g.append(s)
z = 0
for x in g:
    z = max(z, len(x))
print(z)

class UnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(0, n)]
        self.rank = [0] * n

    def root(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.root(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def rootRank(self, x):
        return self.rank[self.root(x)]


N, M = list(map(int, input().split()))
uf = UnionFind(N)
for i in range(M):
    a, b = list(map(int, input().split()))
    a -= 1
    b -= 1
    uf.union(a, b)
z = 0
c = [0] * N
for i in range(N):
    p = uf.root(i)
    c[p] += 1
    if z < c[p]:
        z = c[p]
print(z)

+class UnionFind: +    def __init__(self, n): +        self.parent = [i for i in range(0, n)] +        self.rank = [0] * n + +    def root(self, x): +        if self.parent[x] != x: +            self.parent[x] = self.root(self.parent[x]) +        return self.parent[x] + +    def union(self, x, y): +        x = self.root(x) +        y = self.root(y) +        if self.rank[x] < self.rank[y]: +            self.parent[x] = y +        else: +            self.parent[y] = x +            if self.rank[x] == self.rank[y]: +                self.rank[x] += 1 + +    def same(self, x, y): +        return self.find(x) == self.find(y) + +    def rootRank(self, x): +        return self.rank[self.root(x)] + + -f = [set() for i in range(N)] -v = [False] * N -g = [] -for i in range(0, M): +uf = UnionFind(N) +for i in range(M): -    f[a].add(b) -    f[b].add(a) -for i in range(0, N): -    if v[i]: -        continue -    s = set() -    q = [i] -    while len(q) > 0: -        p = q.pop() -        v[p] = True -        s.add(p) -        for x in f[p]: -            if v[x]: -                continue -            q.append(x) -    g.append(s) +    uf.union(a, b) -for x in g: -    z = max(z, len(x)) +c = [0] * N +for i in range(N): +    p = uf.root(i) +    c[p] += 1 +    if z < c[p]: +        z = c[p]