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
input = sys.stdin.buffer.readline

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

#Union Find

#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]



#初期化
#根なら-size,子なら親の頂点
par = [-1]*n


for _ in range(m):
    a,b = map(int,input().split())
    unite(a-1,b-1)

res = 0
for e in par:
    if e < 0:
        res = max(res,-e)
print(res)

Submission status: Accepted

Solution code:
import sys
stdin = sys.stdin
sys.setrecursionlimit(10**6)
ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
nn = lambda: list(stdin.readline().split())
ns = lambda: stdin.readline().rstrip()

N = 3*10**5

*p, = range(N)
size = [1]*N
def root(x):
    if x == p[x]:
        return x
    p[x] = y = root(p[x])
    return y
def unite(x, y):
    px = root(x); py = root(y)
    if px == py:
        return 0
    sx = size[px]; sy = size[py]
    if sy < sx:
        p[py] = px
        size[px] += sy
    else:
        p[px] = py
        size[py] += sx
    return 1

n,m = na()
ans = 0

for i in range(m):
    a,b = na()
    unite(a,b)

print(max(size))

Submission status: Accepted

Solution code:
class UnionFind():
    def __init__(self, n=0):
        self.d = [-1]*n
    
    def find(self, x):
        if self.d[x] < 0: return x
        self.d[x] = self.find(self.d[x])
        return self.d[x]

    def unite(self, x, y):
        x,y=self.find(x),self.find(y)
        if x==y:return False
        if self.d[x] > self.d[y]: x,y=y,x
        self.d[x] += self.d[y]
        self.d[y] = x
        return True

    def same(self, x,y): return self.find(x)==self.find(y)
    def size(self,x): return -self.d[self.find(x)]
    
N,M=map(int,input().split())
uf = UnionFind(N+1)
for i in range(M):
  a,b=map(int,input().split())
  uf.unite(a,b)
  
print(-min(uf.d))

Submission status: Accepted

Solution code:

class UnionFind():
    # 全ての要素が別グループとして初期化
    def __init__(self, n):
        self.par = [i for i in range(n)]  # 要素の親の番号
        self.rank = [0 for _ in range(n)]  # グループの木の深さ
        self.size = [1 for _ in range(n)]  # グループのサイズ

    # 木の根を求める
    def find(self, x):
        if self.par[x] == x:  # 自分が親 =根
            return x
        else:
            self.par[x] = self.find(self.par[x])  # 自分の親の根を探し、それを自分の親とする(再帰)
            return self.par[x]

    # x,yが属する集合を結合する
    def unite(self, x, y):
        # それぞれの親を見つける
        x = self.find(x)
        y = self.find(y)
        if x == y:
            pass
        else:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.par[y] = x  # yの親をxにする
            self.size[x] += self.size[y]  # 親のサイズのみ正しい

    # x,yが属する集合が同じかを判別する
    def is_same(self, x, y):
        return self.find(x) == self.find(y)

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


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

uf = UnionFind(n)
for i in range(m):
    a,b=map(int,input().split())
    uf.unite(a-1,b-1)

# 正しい結果を得るために全要素をfindで確認する必要がある
for i in range(n):
    uf.find(i)

print(max(uf.size))

Submission status: Accepted

Solution code:

import sys
input = sys.stdin.readline
N,M = map(int,input().split())
F = [i for i in range(N)]

def find(n):
	if F[n] == n:
		return n
	ret = find(F[n])
	F[n] = ret
	return ret

def union(n,m):
	i, j = find(n), find(m)
	F[max(i,j)] = min(i,j)

for _ in range(M):
	A,B = map(int,input().split())
	A -= 1
	B -= 1
	union(A,B)

cnt = [0 for _ in range(N)]
for i in range(N):
	cnt[find(i)] += 1
print(max(cnt))

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 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())


def main():
    from sys import setrecursionlimit, stdin, stderr
    from os import environ
    from collections import defaultdict, deque, Counter
    from math import ceil, floor
    from itertools import accumulate, combinations, combinations_with_replacement
    setrecursionlimit(10**6)
    dbg = (lambda *something: stderr.write("\033[92m{}\033[0m".format(str(something)+'\n'))) if 'TERM_PROGRAM' in environ else lambda *x: 0
    input = lambda: stdin.readline().rstrip()
    LMIIS = lambda: list(map(int,input().split()))
    II = lambda: int(input())
    P = 10**9+7
    INF = 10**18+10

    N,M = LMIIS()
    uf = UnionFind(N+1)
    for i in range(M):
        a,b = LMIIS()
        uf.union(a,b)
    max_size = 0
    roots = uf.roots()
    for r in roots:
        max_size = max(max_size,uf.size(r))
    print(max_size)

    
main()

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 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())

import sys
input = lambda: sys.stdin.readline().rstrip()

n,m= map(int, input().split())
a= [list(map(int, input().split())) for i in range(m)]

UF=UnionFind(n)

for i,j in a:
    i-=1
    j-=1
    UF.union(i,j)

ans=0
for i in range(n):
    ans=max(ans,UF.size(i))
print(ans)

Submission status: Accepted

Solution code:
inpl = lambda: list(map(int,input().split()))
class UnionFind:
    def __init__(self, N=None):
        if N is None or N < 1:
            self.parent = defaultdict(lambda: -1)
        else:
            self.parent = [-1]*int(N)

    def root_rec(self, n):
        if self.parent[n] < 0:
            return n
        else:
            m = self.root(self.parent[n])
            self.parent[n] = m
            return m

    def root(self, n):
        stack = []
        while n >= 0:
            stack.append(n)
            n = self.parent[n]
        m = stack.pop()
        while stack:
            self.parent[stack.pop()] = m
        return m

    def merge(self, m, n):
        rm = self.root(m)
        rn = self.root(n)
        if rm != rn:
            if -self.parent[rm] < -self.parent[rn]:
                rm, rn = rn, rm
            self.parent[rm] += self.parent[rn]
            self.parent[rn] = rm

    def size(self, n):
        return -self.parent[self.root(n)]
    
    def connected(self, m, n):
        return self.root(m) == self.root(n)

    def groups(self):
        if isinstance(self.parent,list):
            return list(filter(lambda i: self.parent[i]<0, range(len(self.parent))))
        else: # self.parent: defaultdict
            return list(filter(lambda i: self.parent[i]<0, self.parent.keys()))
 
    def groups_num(self):
        return len(self.groups())

    def elements(self):
        if isinstance(self.parent,list):
            return range(len(self.parent))
        else:
            return self.parent.keys()

N, M = inpl()
uf = UnionFind(N)
for _ in range(M):
    A, B = inpl()
    uf.merge(A-1, B-1)

ans = max(uf.size(g) for g in uf.groups())
print(ans)

Submission status: Accepted

Solution code:
class DisjointSets:
    def __init__(self,n):
        self.parent = [i for i in range(n)]
        self.siz = [1]*n
        self.grp = n

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

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

    def unite(self,x,y): 
        x = self.root(x)
        y = self.root(y)
        if x == y: 
            return
        if self.siz[x] < self.siz[y]: 
            x,y = y,x
        self.parent[y] = x
        self.siz[x] += self.siz[y]
        self.grp -= 1

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

n,m = map(int,input().split())
ds = DisjointSets(n)
for _ in range(m):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    ds.unite(a,b)
print(max(ds.siz))

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 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())

def main():
    N, M = map(int, input().split())
    u = UnionFind(N)

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

    res = 0
    for i in range(N):
        s = u.size(i)
        if res < s:
            res = s

    print(res)


if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
#Union Find
#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]


N,M = map(int,input().split())
#初期化
#根なら-size,子なら親の頂点
par = [-1]*(N+1)

for i in range(M):
    a,b = map(int,input().split())
    unite(a,b)

ans = 1
for i in range(1,N+1):
    ans = max(ans,size(i))

print(ans)

Submission status: Accepted

Solution code:
import sys
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 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 main():
    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(-uf.parents[uf.find(x)] for x in uf.roots())
    print(ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys
input=sys.stdin.readline


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

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

    def Unite(self,x,y):
        x=self.Find_Root(x)
        y=self.Find_Root(y)

        if x==y:return
        elif self.rank[x]>self.rank[y]:
            self.root[x] +=self.root[y]
            self.root[y]=x
        else:
            self.root[y] +=self.root[x]
            self.root[x]=y
            if self.rank[x]==self.rank[y]:
                self.rank[y] +=1

    def isSameGroup(self,x,y):
        return self.Find_Root(x)==self.Find_Root(y)

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

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

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

    def group_members(self):
        return {i:self.members(i) for i in self.roots()}

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


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

UnionFind=UnionFind(n+1)
for a,b in AB:
    if UnionFind.isSameGroup(a,b) is False:
        UnionFind.Unite(a,b)

ans=0
for i in range(1,n+1):
    cnt=UnionFind.size(i)
    if ans<cnt:
        ans=cnt
print(ans)

Submission status: Accepted

Solution code:
# coding: utf-8
N,M = map(int,input().split())

par = [i for i in range(N+1)]
rank = [0 for i in range(N+1)]
 
def find(x):
    if x==par[x]:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
 
 
def unite(x,y):
    rx=find(x)
    ry=find(y)

    if rx==ry:
        return
    
    
    if rank[rx]<rank[ry]:
        par[rx]=ry
    else:
        par[ry]=rx

    if rank[rx]==rank[ry]:
        rank[rx]+=1
 

def some(x,y):
    return find(x)==find(y)
 
for i in range(M):
    a,b=map(int,input().split())
    unite(a,b)

for i in range(N):
    find(i+1)

cnt = [0 for i in range(N+1)]

for i in range(N+1):
    cnt[par[i]]+=1

print(max(cnt))

Submission status: Accepted

Solution code:
from math import floor,ceil,sqrt
import fractions
from collections import deque
import itertools
import collections
from heapq import *
N,M=map(int,input().split())
flship=[]
for i in range(M):
    s,e=map(int,input().split())
    if s<e:
        flship.append([s-1,e-1])
    else:
        flship.append([e-1,s-1])
flship=list(map(list, set(map(tuple, flship))))
#print(flship)
tree=[[] for _ in range(N)]
for l in flship:
    tree[l[0]].append(l[1])
    tree[l[1]].append(l[0])
#print(tree)
group=[-1]*N
l=[]
for i in range(N):
    d=deque()
    v=i
    if group[v]==-1:
        d.append(v)
        group[v]=i
    while len(d)>0:
        v=d.popleft()
        for j in tree[v]:
            if group[j]==-1:
                group[j]=i
                d.append(j)
    #print(group)
c=collections.Counter(group)
values=list(c.values())	#aのCollectionのvalue値のリスト(n_1こ、n_2こ…)
key=list(c.keys())	#先のvalue値に相当する要素のリスト(要素1,要素2,…)
ans=0
for i in range(len(key)):
    ans=max(ans,values[i])
print(ans)

Submission status: Accepted

Solution code:
# 参考URL https://note.nkmk.me/python-union-find/
class UnionFind():
    # parents
    # 各要素の親要素の番号を格納するリスト
    # 要素が根（ルート）の場合は-(そのグループの要素数)を格納する
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    # find(x)
    # 要素xが属するグループの根を返す
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    # union(x, y)
    # 要素xが属するグループと要素yが属するグループとを併合する
    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

    # size(x)
    # 要素xが属するグループのサイズ（要素数）を返す
    def size(self, x):
        return -self.parents[self.find(x)]

    # same(x, y)
    # 要素x, yが同じグループに属するかどうかを返す
    def same(self, x, y):
        return self.find(x) == self.find(y)

    # members(x)
    # 要素xが属するグループに属する要素をリストで返す
    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    # roots()
    # すべての根の要素をリストで返す
    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    # group_count()
    # グループの数を返す
    def group_count(self):
        return len(self.roots())

    # all_group_members
    # {ルート要素: [そのグループに含まれる要素のリスト], ...}の辞書を返す
    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    # __str__()
    # print()での表示用
    # ルート要素: [そのグループに含まれる要素のリスト]を文字列で返す
    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

from sys import stdin
def input():
    return stdin.readline().strip()

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

uf = UnionFind(n)

for _ in range(m):
    i, j = map(int, input().split())
    uf.union(i-1, j-1)

ans = 0
for i in uf.roots():
    j = uf.size(i)
    if ans < j:
        ans = j

print(ans)

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(10**9)


def unite(par, i, j):
    j = get_par(par, j)
    par[j] = get_par(par, i)

def get_par(par, p):
    while par[p] != p:
        p = par[p]
    return par[p]

def resolve():
    n,m = map(int, input().split())
    cnt = [1 for _ in range(n+1)]
    par = [i for i in range(n+1)]

    for i in range(m):
        a,b = map(int, input().split())
        aa = get_par(par, a)
        bb = get_par(par, b)
        # unite
        if aa == bb:
            continue
        if cnt[aa] > cnt[bb]:
            par[bb] = aa
            cnt[aa] += cnt[bb]
        else:
            par[aa] = bb
            cnt[bb] += cnt[aa]
    #     print(a,b,cnt)

    # print(cnt)
    print(max(cnt))

if __name__ == "__main__":
    resolve()

Submission status: Accepted

Solution code:
#dt = {} for i in x: dt[i] = dt.get(i,0)+1
import sys;input = sys.stdin.readline
inp,ip = lambda :int(input()),lambda :[int(w) for w in input().split()]

import resource,sys
#resource.setrlimit(resource.RLIMIT_STACK,(2**29,-1))
sys.setrecursionlimit(10**6)

def dfs(u):
    global graph,vis
    vis.add(u)
    for i in graph[u]:
        if i not in vis:
            dfs(i)

n,m = ip()
graph = {i:[] for i in range(1,n+1)}
for i in range(m):
    a,b = ip()
    graph[a].append(b)
    graph[b].append(a)
for i in graph:
    graph[i] = list(set(graph[i]))
vis = set()
ans = -1
prev = 0
for i in range(1,n+1):
    if i not in vis:
        dfs(i)
        t = len(vis)
        ans = max(ans,t-prev)
        prev = t
print(ans)

Submission status: Accepted

Solution code:
n,m=map(int, input().split())

#xの根を求める
def find(x):
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]
        
#xとyの属する集合の併合
def unite(x,y):
    x = find(x)
    y = find(y)
    
    if x == y:
        return False
    else:
        #sizeの大きいほうがx
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True

#xとyが同じ集合に属するかの判定
def same(x,y):
    return find(x) == find(y)

#xが属する集合の個数
def size(x):
    return -par[find(x)]

#初期化
#根なら-size,子なら親の頂点
par = [-1]*n

for _ in range(m):
    a,b=map(int,input().split())
    unite(a-1,b-1)
ans=0
for i in range(n):
    if size(i)>ans:
        ans=size(i)
print(ans)

Submission status: Accepted

Solution code:
n,m=map(int,input().split())
par=[-1]*n

# this par & rank are initialized lists
def find(x):
    global par
    if par[x]<0:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
        
def unite(x,y):
    x,y=find(x),find(y)
    global par
    if x==y:return False
    else:
        if par[x]>par[y]:x,y=y,x
        par[x]+=par[y]
        par[y]=x
        return True

def size(x):
    return -par[find(x)]
def same(x,y):
    return find(x)==find(y)


for i in range(m):
  a,b=map(int,input().split())
  unite(a-1,b-1)

par.sort()
print(-par[0])

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline

n, m = map(int, input().split())
from collections import defaultdict
class UnionFind:
    def __init__(self, n):
        class KeyDict(dict):
            # 辞書にないときの対応
            def __missing__(self,key):
                self[key] = key
                return key
        self.parent = KeyDict()
        self.rank = defaultdict(int)
        self.weight = defaultdict(int)

    # 根を探す
    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            # 経路圧縮
            # 自分自身じゃない場合は、上にさかのぼって検索(再帰的に)
            y = self.find(self.parent[x])           
            self.weight[x] += self.weight[self.parent[x]]   #圧縮時にweightを更新(和)
            self.parent[x] = y      #親の置き換え(圧縮)
            return self.parent[x]

    # 結合
    def union(self, x, y):
        x = self.find(x)
        y = self.find(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 weighted_union(self, x, y, w):
        # print("unite",x,y,w,self.weight)
        px = self.find(x)
        py = self.find(y)
        # 低い方を高い方につなげる(親のランクによる)
        # if px == py: return 0
        if self.rank[px] < self.rank[py]:
            self.parent[px] = py
            self.weight[px] = - w - self.weight[x] + self.weight[y]
        else:
            self.parent[py] = px
            self.weight[py] =  w + self.weight[x] - self.weight[y]
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1
        return 0

    # 判定
    def judge(self, x, y):
        return self.find(x) == self.find(y)

cnt = defaultdict(int)
uf = UnionFind(n)
for i in range(m):
    a,b = map(int, input().split())
    a -= 1
    b -= 1
    if not uf.judge(a,b): uf.union(a,b)
for i in range(n):
    cnt[uf.find(i)] += 1

print(max([cnt[k] for k in cnt.keys()]))

Submission status: Accepted

Solution code:
N,M=map(int,input().split())
bridge=[]
for i in range(M):
  a,b=map(int,input().split())
  bridge.append((a-1,b-1))


par=[i for i in range(N)]
size=[1 for i in range(N)]
def find(x):
  if par[x]==x:
    return x
  else:
    par[x]=find(par[x])
    return par[x]
def union(a,b):
  x=find(a)
  y=find(b)
  if x!=y:
    if size[x]<size[y]:
      par[x]=par[y]
      size[y]+=size[x]
    else: 
      par[y]=par[x]
      size[x]+=size[y]
  else:
    return

for i in bridge:
    union(i[0],i[1])


print(max(size))

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(10 ** 9)

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

root = [-1] * n

def r(x):
    if root[x] < 0:
        return x
    else:
        root[x] = r(root[x])
        return root[x]

def unite(x, y):
    x = r(x)
    y = r(y)
    if x == y:
        return
    root[x] += root[y]
    root[y] = x

def size(x):
    x = r(x)
    return -root[x]

for i in range(m):
    x, y = map(int, input().split())
    x -= 1
    y -= 1
    unite(x,y)

max_size = max(map(size, range(n)))

print(max_size)

Submission status: Accepted

Solution code:
import collections
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 7)

class UnionFindPathCompression():
    def __init__(self, n):
        self.parents = list(range(n))
        self.rank = [1]*n
        self.size = [1]*n
        

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

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

        if px == py:
            return
        else:
            if self.rank[px] < self.rank[py]:
                self.parents[px] = py
                self.size[py] += self.size[px]
            else:
                self.parents[py] = px
                self.size[px] += self.size[py]
                #ランクの更新
                if self.rank[px] == self.rank[py]:
                    self.rank[px] += 1


N,M = map(int,input().split())
ufpc = UnionFindPathCompression(N)
AB = [list(map(int, input().split())) for _ in range(M)]
for a,b in AB:
    a,b = a-1,b-1
    ufpc.union(a,b)
    
for i in range(N):
    ufpc.find(i)

c = collections.Counter(ufpc.parents)
score_sorted = sorted(c.items(), key=lambda x:-x[1])
print(score_sorted[0][1])

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 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())
n,m=map(int,input().split())
uf=UnionFind(n)
fr=[set() for _ in range(n)]
for i in range(m):
    a,b=map(int,input().split())
    fr[a-1].add(b-1)
    fr[b-1].add(a-1)
    uf.union(a-1,b-1)
x=0
for i in range(n):
  x=max(x,uf.size(i))
print(x)

Submission status: Accepted

Solution code:
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [0] * (n + 1)
        self.size = [1] * (n + 1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    # 併合
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = x
            self.size[x] += self.size[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    # 同じ集合に属するか判定
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

import sys
import math
import copy
from heapq import heappush, heappop, heapify
from functools import cmp_to_key
from bisect import bisect_left, bisect_right
from collections import defaultdict, deque, Counter
# sys.setrecursionlimit(1000000)

# input aliases
input = sys.stdin.readline
getS = lambda: input().strip()
getN = lambda: int(input())
getList = lambda: list(map(int, input().split()))
getZList = lambda: [int(x) - 1 for x in input().split()]

INF = float("inf")
MOD = 10**9 + 7
divide = lambda x: pow(x, MOD-2, MOD)


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

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    # 併合
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = x
            self.size[x] += self.size[y]
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    # 同じ集合に属するか判定
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

def solve():
    n, m = getList()
    uf = UnionFind(n + 1)
    for i in range(m):
        a, b = getList()
        if not uf.same_check(a, b):
            uf.union(a, b)

    print(max(uf.size))
def main():
    n = getN()
    for _ in range(n):
        solve()

    return
if __name__ == "__main__":
    # main()
    solve()