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



Sample input:
5 3
1 2
3 4
5 1


Sample output:
3

Submission status: Accepted

Solution code:
import sys
import numpy as np
i4 = np.int32
i8 = np.int64


if sys.argv[-1] == 'ONLINE_JUDGE':
    from numba.types import Array, int64
    from numba.pycc import CC
    cc = CC('my_module')

    @cc.export('solve', (Array(int64, 2, 'C'), int64))
    def solve(ab, N):
        parents = np.arange(N)
        depth = np.zeros(N, i8)

        def uf_find(x):
            while True:
                if parents[x] == x:
                    return x
                else:
                    x = parents[x]

        def uf_union(x, y):
            x = uf_find(x)
            y = uf_find(y)
            if x == y:
                return

            if depth[x] == depth[y]:
                depth[x] += 1
                parents[y] = x
            elif depth[x] > depth[y]:
                parents[y] = x
            else:
                parents[x] = y

        for i in range(ab.shape[0]):
            uf_union(ab[i, 0], ab[i, 1])
        num = np.zeros(N, i8)
        for i in range(N):
            p = uf_find(i)
            num[p] += 1
        return np.amax(num)

    cc.compile()
    exit(0)
else:
    from my_module import solve


def main(in_file):
    stdin = open(in_file)
    N, M = [int(x) for x in stdin.readline().split()]
    ab = (np.fromstring(stdin.read(), i8, sep=' ') - 1).reshape(-1, 2)
    ans = solve(ab, N)
    print(ans)


if __name__ == '__main__':
    main(0)

Submission status: Accepted

Solution code:
class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size))
        self.height = [0] * size
        self.size = [1] * size
        self.componentCount = size

    def root(self, index):
        if self.parent[index] == index:  # 根の場合
            return index
        rootIndex = self.root(self.parent[index])  # 葉の場合親の根を取得
        self.parent[index] = rootIndex  # 親の付け直し
        return rootIndex

    def union(self, index1, index2):  # 結合
        root1 = self.root(index1)
        root2 = self.root(index2)

        if root1 == root2:  # 連結されている場合
            return

        self.componentCount -= 1  # 連結成分を減らす

        if self.height[root1] < self.height[root2]:
            self.parent[root1] = root2  # root2に結合
            self.size[root2] += self.size[root1]
        else:
            self.parent[root2] = root1  # root1に結合
            self.size[root1] += self.size[root2]
            if self.height[root1] == self.height[root2]:
                self.height[root1] += 1
        return

    def isSameRoot(self, index1, index2):
        return self.root(index1) == self.root(index2)

    def sizeOfSameRoot(self, index):
        return self.size[self.root(index)]

N, M = map(int, input().split())
tree = UnionFind(N)

for _ in range(M):
    a, b = map(lambda a: int(a) - 1, input().split())
    tree.union(a, b)

ans = 1
for i in range(N):
    ans = max(ans, tree.sizeOfSameRoot(i))
print(ans)

Submission status: Accepted

Solution code:
# compiled by pythran
"""
# pythran export main2()
import numpy as np
i4 = np.int32
i8 = np.int64


def uf_find(x, parents):
    while True:
        if parents[x] == x:
            return x
        else:
            x = parents[x]


def uf_union(x, y, parents, depth):
    x = uf_find(x, parents)
    y = uf_find(y, parents)
    if x == y:
        return

    if depth[x] == depth[y]:
        depth[x] += 1
        parents[y] = x
    elif depth[x] > depth[y]:
        parents[y] = x
    else:
        parents[x] = y


def main(in_file):
    stdin = open(in_file)
    N, M = [int(x) for x in stdin.readline().split()]
    parents = np.arange(N)
    depth = np.zeros(N, i8)
    for i in range(M):
        a, b = [int(x) - 1 for x in stdin.readline().split()]
        uf_union(a, b, parents, depth)
    num = np.zeros(N, i8)
    for i in range(N):
        p = uf_find(i, parents)
        num[p] += 1
    ans = np.amax(num)
    print(ans)


def main2():
    main('/dev/stdin')
"""
import os, sys
p = os.path.dirname(__file__)
pymain = os.path.join(p, "a.out")
if len(sys.argv) == 1:
    import subprocess
    if p == "":
        pymain = "./" + pymain
    subprocess.call(pymain)
else:
    import gzip, base64, stat
    gz = b'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'
    bin = gzip.decompress(base64.b64decode(gz))
    with open(pymain, "wb") as f:
        f.write(bin)
    os.chmod(pymain, 0o775)

Submission status: Accepted

Solution code:
import networkx as nx
from networkx.utils.union_find import UnionFind
n,m=map(int,input().split())
if m==0:print(1);exit()
a=[[i for i in input().split()] for _ in range(m)]
g=nx.Graph()
uf=UnionFind()
for x in a:
     uf.union(x[0],x[1])
print(len(max(uf.to_sets(),key=len)))

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys

def main():
    class UnionFind():
        def __init__(self, n):
            self.n = n
            self.parents = [-1] * n

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

        def union(self, x, y):
            x = self.find(x)
            y = self.find(y)

            if x == y:
                return

            if self.parents[x] > self.parents[y]:
                x, y = y, x

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

        def size(self, x):
            return -self.parents[self.find(x)]

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

        def members(self, x):
            root = self.find(x)
            return [i for i in range(self.n) if self.find(i) == root]

        def roots(self):
            return [i for i, x in enumerate(self.parents) if x < 0]

        def group_count(self):
            return len(self.roots())

        def all_group_members(self):
            return {r: self.members(r) for r in self.roots()}

        def __str__(self):
            return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
    
    input = sys.stdin.readline
    n, m = map(int, input().split())
    uf = UnionFind(n)
    for _ in range(m):
        a, b = map(lambda x:int(x) - 1, input().split())
        uf.union(a, b)
    
    ans = max([-i for i in uf.parents])
    print(ans)

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
from networkx import*
_,*t=map(str.split,open(0))
print(max(1,1,*map(len,vars()[dir()[177]](Graph(t)))))

Submission status: Accepted

Solution code:
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

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

    def size(self, x):
        return -self.parents[self.find(x)]

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

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

def main():
  n, m = map(int, input().split())
  uf = UnionFind(n)

  for i in range(m):
    a, b = map(int, input().split())
    a -= 1; b-= 1;
    uf.union(a, b)
  
  ans = 0
  for i in range(n):
    ans = max(ans, uf.size(i))
      
  print(ans)
  
main()

Submission status: Accepted

Solution code:
from networkx import*
print(max(map(len,connected_components(Graph([*map(str.split,open(0)),'!!'][1:])))))

Submission status: Accepted

Solution code:
import networkx as nx
n,m=map(int,input().split())
if m==0:print(1);exit()
a=[[i for i in input().split()] for _ in range(m)]
g=nx.Graph()
for x in a:
     g.add_edge(x[0],x[1])
print(len(max(nx.connected_components(g),key=len)))

Submission status: Accepted

Solution code:
from networkx import*
print(max(*map(len,connected_components(Graph([*map(str.split,open(0))][1:]))),1,1))

Submission status: Accepted

Solution code:
import networkx as nx
n,m=map(int,input().split())
if m==0:print(1);exit()
a=[[i for i in input().split()] for _ in range(m)]
g=nx.Graph()
for x in a:
     g.add_edge(x[0],x[1])
print(len(sorted(nx.connected_components(g),key=len,reverse=True)[0]))

Submission status: Accepted

Solution code:
import sys

n,m=map(int,next(sys.stdin).split())
adj=[[] for _ in range(n)]
for _ in range(m):
    a,b=map(int,next(sys.stdin).split())
    a,b=a-1,b-1
    adj[a].append(b)
    adj[b].append(a)

ans=0
vis=[0]*n
for i in range(n):
    if vis[i]:
        continue
    vis[i]=1
    k=0
    stk=[i]
    while stk:
        u=stk.pop()
        k+=1
        for v in adj[u]:
            if vis[v]:
                continue
            vis[v]=1
            stk.append(v)
    ans=max(ans,k)

print(ans)

Submission status: Accepted

Solution code:
n,m=map(int,input().split())
adj=[[] for _ in range(n)]
for _ in range(m):
    a,b=map(int,input().split())
    a,b=a-1,b-1
    adj[a].append(b)
    adj[b].append(a)

ans=0
vis=[0]*n
for i in range(n):
    if vis[i]:
        continue
    vis[i]=1
    k=0
    stk=[i]
    while stk:
        u=stk.pop()
        k+=1
        for v in adj[u]:
            if vis[v]:
                continue
            vis[v]=1
            stk.append(v)
    ans=max(ans,k)

print(ans)

Submission status: Accepted

Solution code:
import sys

n,m=map(int,next(sys.stdin).split())
adj=[[] for _ in range(n)]
for _ in range(m):
    ln=next(sys.stdin)
    a,b=map(int,ln.split())
    a,b=a-1,b-1
    adj[a].append(b)
    adj[b].append(a)

ans=0
vis=[0]*n
for i in range(n):
    if vis[i]:
        continue
    vis[i]=1
    k=0
    stk=[i]
    while stk:
        u=stk.pop()
        k+=1
        for v in adj[u]:
            if vis[v]:
                continue
            vis[v]=1
            stk.append(v)
    ans=max(ans,k)

print(ans)

Submission status: Accepted

Solution code:
from networkx import*
_,*t=map(str.split,open(0))
print(max(1,1,*map(len,connected_components(Graph(t)))))

Submission status: Accepted

Solution code:

import collections
from functools import lru_cache
import bisect

INF = float("inf")
ZERO = 0
ONE = 1


def read():
    return input().strip()


def readInt():
    return int(input().strip())


def readList():
    return list(map(int, input().strip().split()))


def solve(N, M, arr):
    graph = collections.defaultdict(list)

    for u, v in arr:
        u -= 1
        v -= 1
        graph[u].append(v)
        graph[v].append(u)

    seen = [False] * N
    ans = 0

    for i in range(N):
        if not seen[i]:
            seen[i] = True
            q = collections.deque([i])
            componentSize = 0

            while q:
                curr = q.popleft()
                componentSize += 1

                for nei in graph[curr]:
                    if not seen[nei]:
                        seen[nei] = True
                        q.append(nei)

            ans = max(ans, componentSize)

    return ans


N, M = readList()
arr = set()

for _ in range(M):
    arr.add(tuple(sorted(readList())))

print(solve(N, M, arr))