Problem:
 Score : 400 points    Problem Statement On a planet far, far away, M languages are spoken. They are conveniently numbered 1 through M .  For CODE FESTIVAL 20XX held on this planet, N participants gathered from all over the planet.  The i -th (1≦i≦N) participant can speak K_i languages numbered L_{i,1}, L_{i,2}, ..., L_{i,{}K_i} .  Two participants A and B can communicate with each other if and only if one of the following conditions is satisfied:   There exists a language that both A and B can speak.  There exists a participant X that both A and B can communicate with.   Determine whether all N participants can communicate with all other participants.      Constraints  2≦N≦10^5  1≦M≦10^5  1≦K_i≦M  ( The sum of all K_i)≦10^5  1≦L_{i,j}≦M  L_{i,1}, L_{i,2}, ..., L_{i,{}K_i} are pairwise distinct.       Partial Score  200 points will be awarded for passing the test set satisfying the following: N≦1000 , M≦1000 and ( The sum of all K_i)≦1000 .  Additional 200 points will be awarded for passing the test set without additional constraints.         Input The input is given from Standard Input in the following format:  N  M  K_1  L_{1,1}  L_{1,2}  ...  L_{1,{}K_1}  K_2  L_{2,1}  L_{2,2}  ...  L_{2,{}K_2}  :  K_N  L_{N,1}  L_{N,2}  ...  L_{N,{}K_N}       Output If all N participants can communicate with all other participants, print YES . Otherwise, print NO .        Sample Input 1 4 6
3 1 2 3
2 4 2
2 4 6
1 6      Sample Output 1 YES  Any two participants can communicate with each other, as follows:   Participants 1 and 2 : both can speak language 2 .  Participants 2 and 3 : both can speak language 4 .  Participants 1 and 3 : both can communicate with participant 2 .  Participants 3 and 4 : both can speak language 6 .  Participants 2 and 4 : both can communicate with participant 3 .  Participants 1 and 4 : both can communicate with participant 2 .   Note that there can be languages spoken by no participant.       Sample Input 2 4 4
2 1 2
2 1 2
1 3
2 4 3      Sample Output 2 NO  For example, participants 1 and 3 cannot communicate with each other.

Solution (Python):
N, M = map(int, input().split())
L = {}
for i in range(N):
    A = list(map(int, input().split()))
    for j, a in enumerate(A):
        if j == 0:
            continue
        if not a-1 in L.keys():
            L[a-1] = [i]
        else:
            L[a-1].append(i)

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

    
    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.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

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

union = UnionFind(N)

for list_l in L.values():
    for l in list_l:
        union.Unite(l, list_l[0])

ans = "YES"
for i in range(N):
    if not union.isSameGroup(0, i):
        ans = "NO"
print(ans)

Solution (Python):
from collections import deque
N,M=map(int,input().split())
tree=[[] for _ in range(N+M)]   


for i in range(N):                      
    l=list(map(int,input().split()))
    K=l[0]
    n=len(l)
    for j in range(1,n):                
        tree[i].append(l[j]+N-1)
        tree[l[j]+N-1].append(i)



d=deque()
seen=[0]*(N+M)              
d.append(0)                 
while len(d)>0:             
                            
    v=d.popleft()
    seen[v]=1               
    for i in tree[v]:
        if seen[i]==0:
            d.append(i)


if sum(seen[:N])==N:        
    print("YES")
else:
    print("NO")

Solution (Python):
from collections import deque
N,M=map(int,input().split())
tree=[[] for _ in range(N+M)]

for i in range(N):
    l=list(map(int,input().split()))
    K=l[0]
    n=len(l)
    for j in range(1,n):
        tree[i].append(l[j]+N-1)
        tree[l[j]+N-1].append(i)


d=deque()
seen=[0]*(N+M)
d.append(0)
while len(d)>0:
    v=d.popleft()
    seen[v]=1
    for i in tree[v]:
        if seen[i]==0:
            d.append(i)


if sum(seen[:N])==N:
    print("YES")
else:
    print("NO")

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

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

    def union(self, x, y):
        x = self.root(x)
        y = self.root(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.root(x)]

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

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

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

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

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

    def __str__(self):
        return ''.join('{}: {}'.format(r, self.members(r)) for r in self.all_roots())

n, m = map(int, input().split())
uf = UnionFind(m+n)


kl = [tuple(map(int,input().split())) for i in range(n)]

for i in range(n):
    for j in range(1,kl[i][0]+1):
        uf.union(m+i,kl[i][j]-1)

for i in range(1,n):
    if not uf.is_same(m,m+i):
        print('NO')
        exit()

print('YES')

Solution (Python):





N,M = map(int,input().split())
from collections import defaultdict
E = [[],[]]
E[0] = [[] for i in range(M)]
E[1] = [[] for i in range(N)]

for i in range(N):
  langs = list(map(int,input().split()))[1:]
  for lang in langs:
    E[1][i].append((0,lang-1))
    E[0][lang-1].append((1,i))
    

from collections import deque
q = deque([])

q.append((1,0))
seen = [[],[]]
seen[0] = [False for i in range(M)]
seen[1] = [False for i in range(N)]

while q:
  kind,v = q.popleft()
  if seen[kind][v]:
    continue
  seen[kind][v] = True
  children = E[kind][v]
  for child in children:
    q.append([child[0],child[1]])
    
for s in seen[1]:
  if not s:
    print("NO")
    break
else:
  print("YES")

Solution (Python):
import sys

sys.setrecursionlimit(10**9)

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

def dfs(num):
    visited[num]=1
    for item in way[num]:
        if visited[item]==0:
            dfs(item)
    return 

mem=[-1]*M
way=[[] for i in range(N)]
visited=[0]*N
for n in range(N):
    temp=list(map(int,input().split()))
    
    for i in range(temp[0]):
        if mem[temp[i+1]-1]==-1:
            mem[temp[i+1]-1]=n
        else:
            way[mem[temp[i+1]-1]].append(n)
            way[n].append(mem[temp[i+1]-1])

for i in range(N):
    way[i]=list(set(way[i]))

dfs(0)

if visited.count(0)==0:
    print("YES")
else:
    print("NO")

Solution (Python):
n,m=map(int,input().split())
import collections
d=collections.defaultdict(int)
class unionfind:
    def __init__(self, n):
        self.n = n
        self.root = [-1]*(n+1)
        self.rnk = [0]*(n+1)
    def find(self, x):
        if(self.root[x] < 0):
            return x
        else:
            self.root[x] = self.find(self.root[x])
            return self.root[x]
    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if(x == y):
            return 
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x
        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def count(self, x):
        return -self.root[self.find(x)]
uf=unionfind(n)
for i in range(1,n+1):
    l=list(map(int,input().split()))
    for j in l[1:]:
        if d[j]==0:
            d[j]=i
        else:
            uf.unite(d[j],i)
if uf.count(1)==n:
    print("YES")
else:
    print("NO")

Solution (Python):
from collections import deque
n,m=map(int,input().split())
graph=[[] for i in range(n+m)]
for i in range(n):
    l=list(map(int,input().split()))
    for j in range(1,l[0]+1):
        graph[n-1+l[j]].append(i)
        graph[i].append(n-1+l[j])
visited=[False]*(n+m)
Q=deque([0])
while Q:
    v=Q.popleft()
    for i in graph[v]:
        if visited[i]:continue
        Q.append(i)
        visited[i]=True
if False in visited[:n]:print("NO")
else:print("YES")

Solution (Python):
import bisect
import copy
import heapq
import sys
import itertools
import queue
from collections import deque
input = sys.stdin.readline
sys.setrecursionlimit(1000000)
mod = 10 ** 9 + 7

def read_values(): return map(int, input().split())
def read_index(): return map(lambda x: int(x) - 1, input().split())
def read_list(): return list(read_values())
def read_lists(N): return [read_list() for n in range(N)]
def init_dp1(init, N): return [init for _ in range(N)]
def init_dp2(init, N, M): return [[init for _ in range(M)] for _ in range(N)]


class V:
    def __init__(self, f, v=None):
        self.f = f
        self.v = v
 
    def __str__(self):
        return str(self.v)
 
    def ud(self, n):
        if n is None:
            return

        if self.v is None:
            self.v = n
            return
        self.v = self.f(self.v, n) 


class UF:
    def __init__(self, N):
        self.parent = [i for i in range(N)]
    
    def get_parent(self, a):
        p = self.parent[a]
        if a == p:
            return a
        
        q = self.get_parent(p)
        self.parent[a] = q
        return q

    def make_pair(self, a, b):
        pa = self.get_parent(a)
        pb = self.get_parent(b)
        if pa == pb:
            return
        
        self.parent[pa] = pb
        self.parent[a] = pb
    
    def is_pair(self, a, b):
        return self.get_parent(a) == self.get_parent(b)


def main():
    N, M = read_values()
    uf = UF(N + M)
    for i in range(N):
        L = read_list()
        for l in L[1:]:
            uf.make_pair(i, l - 1 + N)

    for n in range(1, N):
        if not uf.is_pair(0, n):         
            print("NO")
            return
    print("YES")


if __name__ == "__main__":
    main()

Solution (Python):
n,m = map(int, input().split( ))
p= [i for i in range(n)]+[n+j for j in range(m)]
rk = [0]*(n+m)
def rt(a):
    if a==p[a]:
        return a
    p[a] = rt(p[a])
    return p[a]
def uni(a,b):
    ra = rt(a);rb=rt(b)
    if ra==rb:
        return
    if rk[ra]>rk[rb]:
        p[rb] = ra
    else:
        if rk[ra]==rk[rb]:
            p[ra] = rb
            rk[rb]+=1
        else:
            p[ra]=rb 
    return

kl = {}
for i in range(n):
    ki,*li, = map(int, input().split( ))
    kl[i] = li
for ki in kl:
    for j in range(len(kl[ki])):
        kl[ki][j]-=1

for ki in kl:
    for lij in kl[ki]:
        uni(ki,lij+n)
for i in range(n):
    rt(i)
if len(set(p[:n]))==1:
    print("YES")
else:
    print("NO")

Solution (Python):
import sys
input = sys.stdin.readline

class UnionFind:
    def __init__(self, n):
        '木の初期化をする'
        self.p = [-1] * n
        self.rank = [1]*n
    def find(self, x):
        'x の親を返す'
        if self.p[x] == -1:
            return x
        else:
            self.p[x] = self.find(self.p[x])
            return self.p[x]

    def unite(self, x, y):
        'rankの低い親を高い方のの親にする'
        if not self.same(x,y):
            x = self.find(x)
            y = self.find(y)
            if self.rank[x] > self.rank[y]:
                x,y = y,x
            elif self.rank[x] == self.rank[y]:
                self.rank[y] += 1
            self.p[x] = y
            return True
        else:
            return False

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

n,m = map(int,input().split())
uf = UnionFind(n+m)
for i in range(n):
    kl = list(map(int,input().split()))
    k,L = kl[0],kl[1:]
    for l in L:
        uf.unite(i,l+n-1)
p = uf.find(0)
ans = 'YES'
for i in range(1,n):
    if p != uf.find(i):
        ans = 'NO'
print(ans)

Solution (Python):
n,m=map(int,input().split())
class UnionFind:
    
    
    __slots__ = ["_size", "_first_idx", "_parents"]
    def __init__(self, size: int, first_index: int = 0) -> None:
        self._size = size
        self._first_idx = first_index
        self._parents = [-1] * (size + first_index)
    def find(self, x: int) -> int:
        if self._parents[x] < 0:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]
    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)
    def unite(self, x: int, y: int) -> bool:
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self._parents[x] > self._parents[y]:
            x, y = y, x
        self._parents[x] += self._parents[y]
        self._parents[y] = x
        return True
    def size(self, x: int) -> int:
        return -self._parents[self.find(x)]
    def group_count(self) ->int:
        return sum(1 for i in  self._parents if i<0)
    def connected(self) ->bool:
        return self._parents[self.find(self._first_idx)]==-self._size
lanper=[-1]*m
uf=UnionFind(n)
for i in range(n):
    for j in list(map(int,input().split()))[1:]:
        if lanper[j-1]==-1:lanper[j-1]=i
        else:uf.unite(lanper[j-1],i)
print("YES") if uf.connected() else print("NO")

Solution (Python):
n,m=map(int,input().split())
class UnionFind:
    
    
    __slots__ = ["_size", "_first_idx", "_parents"]
    def __init__(self, size: int, first_index: int = 0) -> None:
        self._size = size
        self._first_idx = first_index
        self._parents = [-1] * (size + first_index)
    def find(self, x: int) -> int:
        if self._parents[x] < 0:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]
    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)
    def unite(self, x: int, y: int) -> bool:
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self._parents[x] > self._parents[y]:
            x, y = y, x
        self._parents[x] += self._parents[y]
        self._parents[y] = x
        return True
    def size(self, x: int) -> int:
        return -self._parents[self.find(x)]
    def group_count(self) ->int:
        return sum(1 for i in  self._parents if i<0)
lanper=[-1]*m
uf=UnionFind(n)
for i in range(n):
    for j in list(map(int,input().split()))[1:]:
        if lanper[j-1]==-1:lanper[j-1]=i
        else:uf.unite(lanper[j-1],i)
print("YES") if uf.size(0)==n else print("NO")

Solution (Python):
n,m=map(int,input().split())
class UnionFind:
    
    
    __slots__ = ["_size", "_first_idx", "_parents"]
    def __init__(self, size: int, first_index: int = 0) -> None:
        self._size = size
        self._first_idx = first_index
        self._parents = [-1] * (size + first_index)
    def find(self, x: int) -> int:
        if self._parents[x] < 0:
            return x
        self._parents[x] = self.find(self._parents[x])
        return self._parents[x]
    def same(self, x: int, y: int) -> bool:
        return self.find(x) == self.find(y)
    def unite(self, x: int, y: int) -> bool:
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self._parents[x] > self._parents[y]:
            x, y = y, x
        self._parents[x] += self._parents[y]
        self._parents[y] = x
        return True
    def size(self, x: int) -> int:
        return -self._parents[self.find(x)]
    def group_count(self) ->int:
        return sum(1 for i in  self._parents if i<0)
lanper=[-1]*m
uf=UnionFind(n)
for i in range(n):
    for j in list(map(int,input().split()))[1:]:
        if lanper[j-1]==-1:lanper[j-1]=i
        else:uf.unite(lanper[j-1],i)
print("YES") if uf.group_count()==1 else print("NO")

Solution (Python):
import sys,collections as cl,bisect as bs
sys.setrecursionlimit(100000)
input = sys.stdin.readline
mod = 10**9+7
Max = sys.maxsize
def l(): 
    return list(map(int,input().split()))
def m(): 
    return map(int,input().split())
def onem(): 
    return int(input())
def s(x): 
    a = []
    if len(x) == 0:
        return []
    aa = x[0]
    su = 1
    for i in range(len(x)-1):
        if aa != x[i+1]:
            a.append([aa,su])
            aa = x[i+1]
            su = 1
        else:
            su += 1
    a.append([aa,su])
    return a
def jo(x): 
    return " ".join(map(str,x))
def max2(x): 
    return max(map(max,x))
def In(x,a): 
    k = bs.bisect_left(a,x)
    if k != len(a) and a[k] ==  x:
        return True
    else:
        return False

def pow_k(x, n):
    ans = 1
    while n:
        if n % 2:
            ans *= x
        x *= x
        n >>= 1
    return ans

"""
def nibu(x,n,r):
    ll = 0
    rr = r
    while True:
        mid = (ll+rr)//2

    if rr == mid:
        return ll
    if (ここに評価入れる):
        rr = mid
    else:
        ll = mid+1
"""

import collections
import itertools
import operator


class UnionFind:
    def __init__(self, x):
        class KeyDict(dict):
            def __missing__(self, key):
                self[key] = key
                return key

        self.parent = KeyDict()
        self.rank = collections.defaultdict(int)
        self.size = collections.defaultdict(lambda: 1)
        if x is not None:
            for elem in range(x+1):
                _, _, _ = self.parent[elem], self.rank[elem],self.size[elem]

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if not self.are_same(x,y):
            xx = self.size[x]
            yy = self.size[y]
            if self.rank[x] < self.rank[y]:
                self.parent[x] = y
                self.size[y] += xx
            else:
                self.parent[y] = x
                self.size[x] += yy
        if self.rank[x] == self.rank[y]:
            self.rank[x] += 1

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

    def are_same(self, x, y):
        '''print(x,y,self.find(x),self.find(y),self.find(x) == self.find(y))'''
        return self.find(x) == self.find(y)

    def grouper(self):
        roots = [(x, self.find(x_par)) for x, x_par in self.parent.items()]
        root = operator.itemgetter(1)
        for _, group in itertools.groupby(sorted(roots, key=root), root):
            yield [x for x, _ in group]

N,M = m()

uf = UnionFind(N-1)

fa = [-1 for i in range(M)]

for i in range(N):
    a = l()

    for j in range(a[0]):
        j += 1
        if fa[a[j]-1] == -1:
            fa[a[j]-1] = i
        else:
            uf.unite(fa[a[j]-1],i)

po = list(uf.grouper())

if len(po) == 1:
    print("YES")
else:
    print("NO")

Solution (Python):
n,m=map(int,input().split())
lang={i:[] for i in range(1,m+1)}
for _ in range(n):
    x=list(map(int,input().split()))
    K=x[0]
    for i in range(1,K+1):
        lan=x[i]
        lang[lan].append(_+1)

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * (n+1)
        
    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())



uni=UnionFind(n)
for i in range(1,m+1):
    lis=lang[i]
    if lis:
        x=lis[0]
        for i in range(1,len(lis)):
            uni.union(x,lis[i])
if uni.group_count()==2:
    print("YES")
else:
    print("NO")

Solution (Python):
import sys
sys.setrecursionlimit(10**7)
n,m = map(int, input().split())
adjacent_list = [[] for i in range(n+1+m+1)]
for i in range(1,n+1):
    for j in list(map(int, input().split()))[1:]:
        adjacent_list[i].append(j+n)
        adjacent_list[j+n].append(i)
finished = set()
def dfs(node):
    finished.add(node)
    for i in adjacent_list[node]:
        if i not in finished:
            dfs(i)
dfs(1)
flag = True
for i in range(1,n+1):
    if i not in finished:
        flag = False
if flag:
    print("YES")
else:
    print("NO")

Solution (Python):
class UnionFind:

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

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

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

    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.height[x] < self.height[y]:
            self.par[x] = y
            self.size[y] += self.size[x]
        else:
            self.par[y] = self.par[x]
            self.size[x] += self.size[y]
            if self.height[x] == self.height[x]:
                self.height[x] += 1

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

N, M = map(int, input().split())
uf = UnionFind(M+1)
Lf = [None]*N
for i in range(N):
    tmp = list(map(int, input().split()))
    K, L = tmp[0], tmp[1:]
    for j in range(K-1):
        uf.unite(L[j], L[j+1])
    Lf[i] = L[0]
r = uf.find(Lf[0])
for i in range(1, N):
    if r != uf.find(Lf[i]):
        print('NO')
        exit()
print('YES')

Solution (Python):
class UnionFindVerSize():
    def __init__(self, N):
        """ N個のノードのUnion-Find木を作成する """
        
        self._parent = [n for n in range(0, N)]
        
        self._size = [1] * N

    def find_root(self, x):
        """ xの木の根(xがどのグループか)を求める """
        if self._parent[x] == x: return x
        self._parent[x] = self.find_root(self._parent[x]) 
        return self._parent[x]

    def unite(self, x, y):
        """ xとyの属するグループを併合する """
        gx = self.find_root(x)
        gy = self.find_root(y)
        if gx == gy: return

        
        if self._size[gx] < self._size[gy]:
            self._parent[gx] = gy
            self._size[gy] += self._size[gx]
        else:
            self._parent[gy] = gx
            self._size[gx] += self._size[gy]

    def get_size(self, x):
        """ xが属するグループのサイズ（個数）を返す """
        return self._size[self.find_root(x)]

    def is_same_group(self, x, y):
        """ xとyが同じ集合に属するか否か """
        return self.find_root(x) == self.find_root(y)

    def calc_group_num(self):
        """ グループ数を計算して返す """
        N = len(self._parent)
        ans = 0
        for i in range(N):
            if self.find_root(i) == i:
                ans += 1
        return ans

import sys

input=sys.stdin.readline

N,M=map(int,input().split())
language={i:[] for i in range(1,M+1)}
for i in range(0,N):
    L=list(map(int,input().split()))
    K=L[0]
    for j in range(1,K+1):
        language[L[j]].append(i)

uf=UnionFindVerSize(N)
for i in range(1,M+1):
    if language[i]:
        p=language[i][0]
        if len(language[i])>1:
            for j in range(1,len(language[i])):
                uf.unite(p,language[i][j])


if uf.calc_group_num()==1:
    print('YES')
else:
    print('NO')

Solution (Python):

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

par=[i for i in range(n+m)]
size=[1 for _ in range(n+m)]
rank=[0 for _ in range(n+m)]
 
def find(x):
    if par[x]==x:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
    
def merge(x,y):
    x=find(x)
    y=find(y)
    if x==y:
        return
    if rank[x]>rank[y]:
        par[y]=x
        size[x]+=size[y]
    else:
        par[x]=y
        size[y]+=size[x]
        if rank[x]==rank[y]:
            rank[y]+=1
            
def same(x,y):
    return find(x)==find(y)

for i in range(n):
    l = list(map(int, input().split()))[1:]
    for j in range(len(l)):
        merge(i, l[j]+n-1)
flg = True
for i in range(1, n):
    if not same(0, i):
        flg = False
print('YES' if flg else 'NO')

Solution (Python):
class UnionFind():
   
   
   def __init__(self, n):
       self.n = n
       
       
       self.root = [-1]*(n+1)
       
       self.rnk = [0]*(n+1)
   
   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.rnk[x] > self.rnk[y]):
           self.root[x] += self.root[y]
           self.root[y] = x
       else:
           self.root[y] += self.root[x]
           self.root[x] = y
           
           if(self.rnk[x] == self.rnk[y]):
               self.rnk[y] += 1
   
   def isSameGroup(self, x, y):
       return self.Find_Root(x) == self.Find_Root(y)
   
   def Count(self, x):
       return -self.root[self.Find_Root(x)]
import sys
input = sys.stdin.readline
n,m=map(int,input().split())
lan=[[] for _ in range(m)]
for i in range(n):
    l=list(map(int,input().split()))
    for j in range(1,l[0]+1):
        lan[l[j]-1].append(i)
h=UnionFind(n)
for i in range(m):
    if len(lan[i])>1:
        for j in range(1,len(lan[i])):
            h.Unite(lan[i][0],lan[i][j])
print("NO" if h.Count(0)-n else "YES")

Solution (Python):

from collections import defaultdict,deque
from heapq import heappush, heappop
from bisect import bisect_left, bisect_right
import sys, random, itertools, math
sys.setrecursionlimit(10**5)
input = sys.stdin.readline
sqrt = math.sqrt
def LI(): return list(map(int, input().split()))
def LF(): return list(map(float, input().split()))
def LI_(): return list(map(lambda x: int(x)-1, input().split()))
def II(): return int(input())
def IF(): return float(input())
def S(): return input().rstrip()
def LS(): return S().split()
def IR(n): return [II() for _ in range(n)]
def LIR(n): return [LI() for _ in range(n)]
def FR(n): return [IF() for _ in range(n)]
def LFR(n): return [LI() for _ in range(n)]
def LIR_(n): return [LI_() for _ in range(n)]
def SR(n): return [S() for _ in range(n)]
def LSR(n): return [LS() for _ in range(n)]
mod = 1000000007
inf = 1e10


def solve():
    n, m = LI()
    par = [i for i in range(n)]
    def root(x):
        if x == par[x]:
            return x
        par[x] = root(par[x])
        return par[x]
    def unite(x, y):
        x = root(x)
        y = root(y)
        if y < x: x, y = y, x
        par[y] = x
        return
    ling = [[] for i in range(m)]
    for i in range(n):
        kl = LI()
        for l in kl[1:]:
            ling[l-1].append(i)
    for l in ling:
        if l:
            l0 = l[0]
            for li in l[1:]:
                unite(l0, li)
    for i in range(n):
        root(i)
    print("YES" if len(set(par)) == 1 else "NO")
    return



if __name__ == '__main__':
    solve()

Solution (Python):
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())
import sys
input=sys.stdin.readline
n,m = map(int, input().split())
uf = UnionFind(m)
lang=set()
for i in range(n):
    lis = list(map(int,input().split()))
    for i in range(1,len(lis)-1):
        lang.add(lis[i]-1)
        uf.union(lis[i]-1,lis[i+1]-1)
    lang.add(lis[-1]-1)
e = next(iter(lang))
if lang == set(uf.members(e)):
    print("YES")
else:
    print("NO")

Solution (Python):
class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0]*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]
  def unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
    else:
      self.par[y] = x
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  
N,M = map(int, input().split())
u = UnionFind(N+M)
for i in range(N):
  inf = list(map(int, input().split()))
  for l in inf[1:]:
    u.unit(i,N+l-1)

ans = all(u.same(i,i+1) for i in range(N-1))
if ans:
  print('YES')
else:
  print('NO')

Solution (Python):
import sys
input = sys.stdin.readline

n, m = map(int, input().split())
g = [[] for _ in range(n)]
d = {}
for i in range(n):
    kl = list(map(int, input().split()))
    L = kl[1:]
    L = [l-1 for l in L]
    for l in L:
        if l not in d:
            d[l] = i
        else:
            g[d[l]].append(i)
            g[i].append(d[l])

from collections import deque
s = deque()
s.append(0)
visit = [-1]*n
visit[0] = 0
while s:
    x = s.pop()
    for nx in g[x]:
        if visit[nx] == -1:
            visit[nx] = 0
            s.append(nx)
if min(visit) != -1:
    print('YES')
else:
    print('NO')