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())
from collections import defaultdict
root=[-1]*(N+M)
def find(i):
    global root
    if root[i]>=0:
        root[i]=find(root[i])
        return root[i]
    return i
def make(a,b):
    global root
    ra=find(a)
    rb=find(b)
    if ra==rb:
        return
    elif root[ra]<=root[rb]:
        root[ra]+=root[rb]
        root[rb]=ra
    else:
        root[rb]+=root[ra]
        root[ra]=rb
    return
for i in range(N):
    X=list(map(int,input().split()))
    for k in range(X[0]):
        make(i,N+X[k+1]-1)
r0=find(0)
flag=True
for i in range(1,N):
    if find(i)!=r0:
        flag=False
        break
if flag:
    print('YES')
else:
    print('NO')

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

e_list = [[] for i in range(N+M)]

for i in range(N):
    D = list(map(int,input().split()))
    for j in range(1,D[0]+1):
        e_list[i].append(N+(D[j]-1))
        e_list[N+(D[j]-1)].append(i)

vi = 0 
from collections import deque
Q = deque([vi])
checked_list = [False]*(N+M)
checked_list[vi]=True
while len(Q)>0:
    v = Q.pop()
    for v1 in e_list[v]:
        if not checked_list[v1]:
            checked_list[v1]=True
            Q.appendleft(v1)
flag=True
for i in range(N):
    if not checked_list[i]:
        flag=False

if flag:
    print("YES")
else:
    print("NO")

Solution (Python):
N, M = map(int,input().split())
H = []
L = [[] for k in range(M+1)]

for k in range(N):
    P = list(map(int,input().split()))[1:]
    H.append(P)
    for e in P:
        L[e].append(k+1)

G = [0 for k in range(N+1)]
G[1] = 1
Q = [H[0]]
while len(Q) > 0:
    ima = Q.pop()
    for tsugi in ima:
        for e in L[tsugi]:
            if G[e] == 0:
                G[e] = 1
                if len(H[e-1]) > 1:
                    Q.append(H[e-1])

for k in range(1,N+1):
    if G[k] == 0:
        print("NO")
        exit(0)
print("YES")

Solution (Python):
N, M = map(int,input().split())
H = []
L = [[] for k in range(M+1)]

for k in range(N):
    P = list(map(int,input().split()))[1:]
    H.append(P)
    for e in P:
        L[e].append(k+1)

G = [0 for k in range(N+1)]
G[1] = 1
Q = [H[0]]
while len(Q) > 0:
    ima = Q.pop()
    for tsugi in ima:
        for e in L[tsugi]:
            if G[e] == 0:
                G[e] = 1
                if len(H[e-1]) > 1:
                    Q.append(H[e-1])

for k in range(1,N+1):
    if G[k] == 0:
        print("NO")
        exit(0)
print("YES")

Solution (Python):
from itertools import*
from math import*
from collections import*
from heapq import*
from bisect import bisect_left,bisect_right
from copy import deepcopy
inf = float("inf")
mod = 10**9+7
from functools import reduce
import sys
sys.setrecursionlimit(10**7)

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

class UnionFind():
    def __init__(self, N):
        self.rank = [0] * N
        self.par = [i for i in range(N)]
        self.counter = [1] * 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 unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            z = self.counter[x] + self.counter[y]
            self.counter[x], self.counter[y] = z, z
        if self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

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

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

uf = UnionFind(N+M)
for i in range(N):
    KL = list(map(int,input().split()))
    for L in KL[1:]:
        uf.unite(i,L+N-1)
ans = "YES"
for i in range(1,N):
    if not uf.same(0,i):
        ans = "NO"
print(ans)

Solution (Python):
N, M = map(int, input().split())

parent = [i for i in range(N + M)]
rank = [0] * (N + M)


def find(i):
    if parent[i] == i:
        return i
    else:
        parent[i] = find(parent[i])
        return parent[i]


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


def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return

    if rank[x] > rank[y]:
        parent[y] = x
    else:
        parent[x] = y
        if rank[x] == rank[y]:
            rank[y] += 1


for i in range(N):
    P = list(map(int, input().split()))
    n = P[0]
    for j in range(1, n + 1):
        unite(i, P[j] - 1 + N)


k = find(0)
for i in range(N):
    if k != find(i):
        print('NO')
        exit()

print('YES')

Solution (Python):
class UnionFindNode(object):
    """
    Union-Find構造
    ノードのグループ併合や、所属グループ判定を高速に処理する
    """

    def __init__(self, group_id, parent=None, value=None):
        self.group_id_ = group_id
        self.parent_ = parent
        self.value = value
        self.size_ = 1

    def __str__(self):
        template = "UnionFindNode(group_id: {}, \n\tparent: {}, value: {}, size: {})"
        return template.format(self.group_id_, self.parent_, self.value, self.size_)

    def is_root(self):
        return not self.parent_

    def root(self):
        parent = self
        while not parent.is_root():
            parent = parent.parent_
            self.parent_ = parent
        return parent

    def find(self):
        parent = self.root()
        return parent.group_id_

    def size(self):
        parent = self.root()
        return parent.size_

    def unite(self, unite_node):
        parent = self.root()
        unite_parent = unite_node.root()

        if parent.group_id_ != unite_parent.group_id_:
            if parent.size() > unite_parent.size():
                unite_parent.parent_ = parent
                parent.size_ = parent.size_ + unite_parent.size_
            else:
                parent.parent_ = unite_parent
                unite_parent.size_ = parent.size_ + unite_parent.size_

    def same(self, node):
        return self.root() == node.root()


N, M = map(int, input().split())
uf = [UnionFindNode(i) for i in range(M)]
l = []
for i in range(N):
    k, *lang = list(map(int, input().split()))
    for j in range(k - 1):
        uf[lang[j] - 1].unite(uf[lang[j + 1] - 1])
    l.append(lang)
r = uf[lang[0] - 1].root()
for i in range(N):
    if uf[l[i][0] - 1].root() != r:
        print('NO')
        exit(0)
print('YES')

Solution (Python):
N,m=map(int,input().split())

L=[]

for i in range(N):
    S=list(map(int,input().split()))
    del S[0]
    L.append(S)


P=[i for i in range(m+1)]
size=[1 for i in range(m+1)]

def find(x):
    if P[x]==x:
        return x
    else:
        return find(P[x])
        
def union(y,z):
    Y=find(y)
    Z=find(z)
    if size[Y]>=size[Z]:
        size[Y]+=size[Z]
        P[Z]=P[Y]
    else:
        size[Z]+=size[Y]
        P[Y]=P[Z]
        
for i in range(len(L)):
    if len(L[i])>=2:
        for j in range(1,len(L[i])):
            if find(L[i][j-1])==find(L[i][j]):
                pass
            else:
                union(L[i][j-1],L[i][j])

F=[0 for i in range(m+1)]
for i in range(len(L)):
    for j in range(len(L[i])):
        F[L[i][j]]=1


cnt=0
for i in range(len(F)):
    if F[i]==1 and P[i]==i:
        cnt+=1
if cnt==1:
    print("YES")
else:
    print("NO")

Solution (Python):
import sys
sys.setrecursionlimit(10**9)
n,m=map(int,input().split())
a=[[]for i in range(n+m)]
for i in range(n):
    s=list(map(int,input().split()))
    for j in s[1:]:
        a[i].append(j+n-1)
        a[n+j-1].append(i)
t=[False]*(n+m)
def g(x):
    t[x]=True
    for i in a[x]:
            if not t[i]:
                g(i)
g(0)
if all(t[:n]):
    print("YES")
else:
    print("NO")

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

def dfs(v):
    used[v] = True
    for _v in adjl[v]:
        if not used[_v]:
            dfs(_v)

n, m = map(int, input().split())
adjl = [[] for v in range(n + m)]
for i in range(n):
    kl = list(map(int, input().split()))
    k = kl[0]
    llist = kl[1:]
    for l in llist:
        adjl[i].append(l + n - 1)
        adjl[l + n - 1].append(i)

used = [False] * (n + m)
dfs(0)

if all(used[:n]):
  print('YES')
else:
  print('NO')

Solution (Python):
N,M=map(int,input().split())
from collections import defaultdict
lang=[-1]*(M+1)
data=defaultdict(int)
def search(l):
    if lang[l]>=0:
        lang[l]=search(lang[l])
    elif lang[l]<0:
        return l
    return lang[l]
def union(i,j,lang):
    iidx=search(i)
    jidx=search(j)
    if iidx==jidx:
        return lang
    elif lang[iidx]<=lang[jidx]:
        lang[iidx]+=lang[jidx]
        lang[jidx]=iidx
    else:
        lang[jidx]+=lang[iidx]
        lang[iidx]=jidx
    return lang
for i in range(N):
    line=list(map(int,input().split()))
    data[line[1]]+=1
    for k in range(1,line[0]):
        data[line[k+1]]+=1
        lang=union(line[k],line[k+1],lang)
L=set()
for k in range(1,1+M):
    if data[k]==0:continue
    L|={search(k)}
if len(L)>1:
    print('NO')
elif len(L)==1:
    print('YES')

Solution (Python):
def init(n):
    global par, rank
    par = [i for i in range(n)]
    rank = [0] * n

def find(x):
    global par
    if par[x] == x:
        return x
    else:
        par[x] = find(par[x])
        return par[x]

def unite(x, y):
    global par, rank
    x = find(x)
    y = find(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]:
            rank[x] += 1

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

N, M = map(int, input().split())
init(N + M)
for i in range(N):
    a = list(map(int, input().split()))
    for L in a[1:]:
        unite(i, L - 1 + N)
ans = "YES"
for i in range(N):
    if not same(0, i):
        ans = "NO"
        break
print(ans)

Solution (Python):
def init(n):
    global par, rank
    par = [i for i in range(n)]
    rank = [0] * n

def find(x):
    global par
    if par[x] == x:
        return x
    else:
        par[x] = find(par[x])
        return par[x]

def unite(x, y):
    global par, rank
    x = find(x)
    y = find(y)
    if x == y:
        return
    if rank[x] < rank[y]:
        par[x] = y
    else:
        par[y] = x
        if rank[x] == rank[y]:
            rank[x] += 1

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

N, M = map(int, input().split())
init(N + M)
for i in range(N):
    a = list(map(int, input().split()))
    for L in a[1:]:
        unite(i, L - 1 + N)
ans = "YES"
for i in range(N):
    if not same(0, i):
        ans = "NO"
        break
print(ans)

Solution (Python):
class UnionFind:
    def __init__(self, x):
        self.__par = list(range(x))
        self.__rank = [0] * x

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.__rank[x] > self.__rank[y]:
            self.__par[y] = x
        else:
            self.__par[x] = y
            if self.__rank[x] == self.__rank[y]:
                self.__rank[y] += 1

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


if __name__ == '__main__':
    n, m = map(int, input().split())
    uf = UnionFind(n + m)

    for i in range(n):
        for l in (int(s) + n - 1 for s in input().split()[1:]):
            uf.unite(i, l)

    print('YES' if all(uf.same(0, v) for v in range(1, n)) else 'NO')

Solution (Python):
import sys
class UnionFind:
    def __init__(self, n):
        
        self.par = [i for i in range(n+1)]
        
        self.rank = [0] * (n+1)
        
        self.count = [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.count[y] += self.count[x]
            self.count[x] = 0
        else:
            self.par[y] = x
            self.count[x] += self.count[y]
            self.count[y] = 0
            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 size(self,x):
        q = UnionFind.find(self,x)
        return self.count[q]

N,M=map(int,input().split())
K=[set() for i in range(M)]
tree=UnionFind(N)
for i in range(N):
    L=[int(i)-1 for i in input().split()]
    for m in L[1:]:
        K[m].add(i)
for i in range(M):
    Ki=list(K[i])
    if len(Ki)==0:
        continue
    for h in range(len(Ki)):
        tree.union(Ki[h],Ki[0])
for i in range(N):
    if not tree.same_check(0,i):
        print('NO')
        sys.exit()
print('YES')

Solution (Python):
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 same_check(self, x, y):
        return self.find(x) == self.find(y)

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if self.rank[x] < self.rank[y]:
            if self.same_check(x, y) != True:
                self.size[y] += self.size[x]
                self.size[x] = 0
            self.par[x] = y
        else:
            if self.same_check(x, y) != True:
               self.size[x] += self.size[y]
               self.size[y] = 0
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
               self.rank[x] += 1

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


N, M = list(map(int, input().split()))
l = [[] for i in range(M)]
uf = UnionFind(N)

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

for i in range(M):
    for j in range(len(l[i]) - 1):
        uf.union(l[i][0], l[i][1 + j])

if uf.siz(1) == N:
    print("YES")
else:
    print("NO")

Solution (Python):
N,M=map(int,input().split())
p_lgngs=[[]for _ in range(N)]
l_peops=[[]for _ in  range(M+1)]
n_isl=0
lset=set()

data=[-1]*(M+1)
rank=[1 ]*(M+1)
def find(x):
  while data[x]!=-1: 
    x=data[x]
  return x
def unite(a,b):
  a,b=find(a),find(b)
  if a!=b:
    if  rank[a]<rank[b]:
      a,b=b,a
    if rank[a]==rank[b]:
      rank[a]+=1
    data[b]=a
    return True
  else: 
    return False
    
for i in range(N):
  k,*L=list(map(int,input().split()))
  p_lgngs[i]+=L
  for ll in L:
    l_peops[ll].append(i)
    lset.add(ll)
  for q in range(1,k):
    if unite(L[q-1], L[q]):
      n_isl-=1
if n_isl+len(lset)==1:
  print("YES")
else:
  print("NO")
exit(0)
print(n_isl+len(lset))

Solution (Python):

class UnionFind():
    def __init__(self, n):
        self.par = [i for i 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]

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

        if x<y:
            self.par[y] = x
        else:
            self.par[x] = y

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


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

for u in range(n):
    line = list(map(int, input().split()))
    k = line[0]
    for l in line[1:]:
        lng = n+l-1
        uf.unite(u, lng)

flag = True
for u in range(1,n):
    if not uf.same(0,u):
        flag = False
        break
if flag:
    print("YES")
else:
    print("NO")

Solution (Python):
n, m = map(int, input().split())
l = [-1]*m
def root(a):
    if l[a] < 0:return a
    l[a] = root(l[a])
    return l[a]
def unite(a,b):
    ra, rb = root(a), root(b)
    if ra == rb:
        return
    if l[ra] > l[rb]:
        ra, rb = rb, ra
    l[ra] += l[rb]
    l[rb] = ra

d = set()
for i in range(n):
    _, *k = list(map(int, input().split()))
    from_ = k[0]-1
    if from_ not in d:
        d.add(from_)
    for j in range(1,len(k)):
        unite(from_, k[j]-1)
        if k[j]-1 not in d:
            d.add(k[j]-1)

if sum(l[i] < 0 for i in d) > 1:
    print("NO")
else:
    print("YES")

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

def dfs(vNow):
    useds[vNow] = True
    for v2 in adjL[vNow]:
        if not useds[v2]:
            dfs(v2)

N, M = map(int, input().split())
adjL = [[] for v in range(N+M)]
for i in range(N):
    K, *Ls = map(int, input().split())
    for L in Ls:
        adjL[i].append(L+N-1)
        adjL[L+N-1].append(i)

useds = [False] * (N+M)
dfs(0)

print('YES' if all(useds[:N]) else 'NO')

Solution (Python):

class UnionFind:
    def __init__(self, numV):
        self.pars = list(range(numV))
        self.ranks = [0] * numV
    def find(self, x):
        if self.pars[x] == x: return x
        else:
            self.pars[x] = self.find(self.pars[x])
            return self.pars[x]
    def union(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y: return
        if self.ranks[x] < self.ranks[y]:
            self.pars[x] = y
        else:
            self.pars[y] = x
            if self.ranks[x] == self.ranks[y]:
                self.ranks[x] += 1
    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):
    K, *Ls = map(int, input().split())
    for L in Ls:
        UF.union(i, L+N-1)

pars = [UF.find(i) for i in range(N)]
print('YES' if len(set(pars)) == 1 else 'NO')

Solution (Python):
n, m = map(int, input().split())
kl = []
for i in range(n):
    kl.append([int(m) for m in input().split()])
class UnionFind:
    def __init__(self, n):
        
        self.par = [i for i in range(n+1)]
        
        self.rank = [0] * (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
        else:
            self.par[y] = x
        
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

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

u = UnionFind(n + m)
for i in range(n):
    ki = kl[i][0]
    for j in range(1, ki + 1):
        u.union(m + i + 1, kl[i][j])
print(('NO', 'YES')[all(u.same_check(m + 1, m + i + 1) for i in range(n))])

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

N, M = map(int, input().split())
P_to_L = [[] for i in range(N)]  
L_to_P = [[] for i in range(M)]  

for i in range(N):
    info = list(map(int, input().split()))
    for l in info[1:]:
        P_to_L[i].append(l - 1)
        L_to_P[l - 1].append(i)


P_visited = [False] * N  
L_visited = [False] * M  


def dfs(n, p_to_l):
    if p_to_l:
        P_visited[n] = True
        for to in P_to_L[n]:
            if not L_visited[to]:
                dfs(to, False)
    else:
        L_visited[n] = True
        for to in L_to_P[n]:
            if not P_visited[to]:
                dfs(to, True)


dfs(0, True)
print('YES' if all(P_visited) else 'NO')

Solution (Python):
class UnionFind():
    def __init__(self,size):
        self.table=[-1for _ in range(size)]
    def root(self,x):
        while self.table[x]>=0:
            x=self.table[x]
        return x
    def unite(self,x,y):
        s1=self.root(x)
        s2=self.root(y)
        if s1!=s2:
            if self.table[s1]!=self.table[s2]:
                if self.table[s1]<self.table[s2]:
                    self.table[s2]=s1
                else:
                    self.table[s1]=s2
            else:
                self.table[s1]+=-1
                self.table[s2]=s1
        return
    def same(self,x,y):
      return self.root(x)==self.root(y)
n,m=map(int,input().split())
UF=UnionFind(n+m)
for i in range(n):
    for t in map(int,input().split()[1:]):
        UF.unite(i,n+t-1)
print('YNEOS'[len(set(UF.root(i)for i in range(n)))>1::2])

Solution (Python):
class UnionFind():
    def __init__(self,size):
        self.table=[-1for _ in range(size)]
    def root(self,x):
        while self.table[x]>=0:
            x=self.table[x]
        return x
    def unite(self,x,y):
        s1=self.root(x)
        s2=self.root(y)
        if s1!=s2:
            if self.table[s1]!=self.table[s2]:
                if self.table[s1]<self.table[s2]:
                    self.table[s2]=s1
                else:
                    self.table[s1]=s2
            else:
                self.table[s1]+=-1
                self.table[s2]=s1
        return
    def same(self,x,y):
      return self.root(x)==self.root(y)
n,m=map(int,input().split())
UF=UnionFind(n+m)
for i in range(n):
    for t in map(int,input().split()[1:]):
        UF.unite(i,n+t-1)
print('YNEOS'[len(set(UF.root(i)for i in range(n)))>1::2])

Solution (Python):
class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (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
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

  
n,m = (int(i) for i in input().split())
k = []
uf = UnionFind(m)
for i in range(n):
  a = []
  a = list(int(i) for i in input().split())
  a.pop(0)
  k.append(a)
for i in k:
  tmp = i[0]
 
  for j in i[1:]:
   uf.union(tmp,j)
    
 
b = uf.find(k[0][0])
for k in k[1:]:
  if b == uf.find(k[0]):
    continue 
  else:
    print('NO')
    exit()
print('YES')

Solution (Python):
import sys


class Unionfindtree:
    def __init__(self, number):
        self.par = [i for i in range(number)]
        self.rank = [0] * (number)

    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):  
        px = self.find(x)
        py = self.find(y)
        if px == py:
            return
        if self.rank[px] < self.rank[py]:
            self.par[px] = py
        else:
            self.par[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1

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


N,M=map(int,input().split())
K=[set() for i in range(M)]
tree=Unionfindtree(N)
for i in range(N):
    L=[int(i)-1 for i in input().split()]
    for m in L[1:]:
        K[m].add(i)
for i in range(M):
    Ki=list(K[i])
    if len(Ki)==0:
        continue
    for h in range(len(Ki)):
        tree.union(Ki[h],Ki[0])
for i in range(N):
    if not tree.connect(0,i):
        print('NO')
        sys.exit()
print('YES')

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

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

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
            self.size[y] += self.size[x]

        else:
            self.parent[y] = x
            self.size[x] += self.size[y]
            if self.size[x] == self.rank[y]:
                self.rank[x] += 1

    def check_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())
lang_list = []
k_list = []
for i in range(N):
    tmp = tuple(map(int, input().split()))
    k_list.append(tmp[0])
    lang_list.append(tmp[1:])
union_find = UnionFind(M)

for lang in lang_list:
    tmp = lang[0]
    for l in lang[1:]:
        union_find.union(tmp, l)

p = union_find.find(lang_list[0][0])
for lang in lang_list[1:]:
    if p == union_find.find(lang[0]):
        continue
    else:
        print("NO")
        exit()
print("YES")

Solution (Python):
N, M = [int(_) for _ in input().split()]
KL = [[int(_) for _ in input().split()] for _ in range(N)]

UF = list(range(M + 1))


def find(a, x):
    if a[x] != x:
        a[x] = find(a, a[x])
    return a[x]


def unite(a, x, y):
    X = find(a, x)
    Y = find(a, y)
    Z = min(X, Y)
    a[X], a[Y] = Z, Z


def same(a, x, y):
    return find(a, x) == find(a, y)


for kl in KL:
    K, L = kl[0], kl[1:]
    for i in range(K - 1):
        unite(UF, L[i], L[i + 1])
for kl in KL:
    if not same(UF, KL[0][1], kl[1]):
        print('NO')
        exit()
print('YES')

Solution (Python):
from collections import defaultdict
def inpl(): return [int(i) for i in input().split()]
class UnionFind():
    def __init__(self, num):
        self.par = [-1 for _ in range(num)]
    
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            x = self.par[x]
            return self.find(x)
    
    def union(self, x, y):
        rx = self.find(x)
        ry = self.find(y)
        if rx != ry:
            if self.par[rx] < self.par[ry]:
                self.par[ry] = rx
            if self.par[rx] > self.par[ry]:
                self.par[rx] = ry
            else:
                self.par[rx] -= 1
                self.par[ry] = rx
        return
    
lang = defaultdict(lambda: [])
N, M = inpl()
for i in range(N):
    L = inpl()[1:]
    for j in L:
        lang[j].append(i)
CF = UnionFind(N)
for Li in lang.values():
    t = Li[0]
    for j in Li:
        CF.union(t, j)
uni = [i for i in CF.par if i< 0]
if len(uni) == 1:
    print('YES')
else:
    print('NO')

Solution (Python):
from collections import deque
N,M=map(int,input().split())
L=[[] for i in range(M)]
for i in range(N):
  for j,k in enumerate(input().split()):
    if j==0:
      continue
    L[int(k)-1].append(i)
G=[[] for i in range(N)]
for l in L:
  if len(l)>=2:
    for i in range(len(l)-1):
      if l[i+1] not in G[l[i]]:
        G[l[i]].append(l[i+1])
        G[l[i+1]].append(l[i])

V=[False]*N
n=1
dfs_stack=deque([0])
while dfs_stack:
  a=dfs_stack.popleft()
  if not V[a]:
    n+=1
    for b in G[a]:
      if not V[b]:
        dfs_stack.append(b)
  V[a]=True
if V==[True]*N:
  print("YES")
else:
  print("NO")

Solution (Python):
from collections import deque

N, M = map(int, input().split())
EN, EM = [[] for i in range(N)], [[] for i in range(M)]
for i in range(N):
    IP = [int(k) for k in input().split()]
    EN[i] = [a-1 for a in IP[1:]]
    for j in IP[1:]:
        EM[j-1].append(i)

VN, VM = [False for i in range(N)], [False for i in range(M)]
Q = deque()
Q.append(0)
VN[0] = True
while Q:
    tempN = Q.popleft()
    VN[tempN] = True
    for m in EN[tempN]:
        if not VM[m]:
            VM[m] = True
            for n in EM[m]:
                if not VN[n]:
                    VN[n] = True
                    Q.append(n)

if False in VN: print("NO")
else: print("YES")

Solution (Python):
N,M=map(int,input().split())
L=[]
for i in range(N):
    L.append([int(i)-1 for i in input().split()][1:])
K=[len(L[i]) for i in range(N)]
X=[-1 for i in range(M)]
for i in range(N):
    for j in range(K[i]):
        if X[L[i][j]]==-1:
            X[L[i][j]]=i
par=[0 for i in range(N)]
rnk=[0 for i in range(N)]
def init(n):
    for i in range(N):
        par[i]=i
        rnk[i]=0
def find(x):
    if par[x]==x:
        return x
    else:
        par[x]=find(par[x])
        return par[x]
def unite(x,y):
    x=find(x)
    y=find(y)
    if x==y:
        return
    if (rnk[x]<rnk[y]):
        par[x]=y
    else:
        par[y]=x
        if(rnk[x]==rnk[y]):
            rnk[x]+=1
def same(x,y):
    return find(x)==find(y)
init(N)
for i in range(N):
    for j in range(K[i]):
        unite(i,X[L[i][j]])
for i in range(1,N):
    if not(same(0,i)):
        print("NO")
        exit()
print("YES")