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):
def f():
    import sys
    input=sys.stdin.buffer.readline
    sys.setrecursionlimit(10**9)
    n,m=map(int,input().split())
    lang={}
    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)-self._first_idx
        def connected(self) ->bool:
            return self._parents[self.find(self._first_idx)]==-self._size
    uf=UnionFind(n)
    for i in range(n):
        k,*l=map(int,input().split())
        for j in l:
            if j in lang:
                uf.unite(i,lang[j])
            else:
                lang[j]=i
    print("YES")if uf.connected() else print("NO")





if __name__ == "__main__":
    f()

Solution (Python):
import os,io
input=io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
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(m+1)
T=[]
for i in range(n):
  a=list(map(int,input().split()))
  k=a[0]
  for j in range(k-1):
    uf.union(a[j+1],a[j+2])
  T.append(a[1])
failflag=0
for i in range(n):
  if not uf.same(T[0],T[i]):
    failflag=1
if failflag==0:
  print('YES')
else:
  print('NO')

Solution (Python):
import sys, re
from collections import deque, defaultdict, Counter
from math import ceil, sqrt, hypot, factorial, pi, sin, cos, radians
from itertools import accumulate, permutations, combinations, product
from operator import itemgetter, mul
from copy import deepcopy
from string import ascii_lowercase, ascii_uppercase, digits
from bisect import bisect, bisect_left
from fractions import gcd
from heapq import heappush, heappop
from functools import reduce
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
def ZIP(n): return zip(*(MAP() for _ in range(n)))
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
mod = 10 ** 9 + 7

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()
L = [[x-1 for x in LIST()[1:]] for _ in range(N)]
uf = UnionFind(N)
graph = [[] for _ in range(M)]

for i, l in enumerate(L):
	for x in l:
		graph[x].append(i)

for i in range(M):
	if len(graph[i]) <= 1:
		continue
	p = graph[i][0]
	for x in graph[i][1:]:
		uf.union(p, x)

num_group = uf.group_count()
print("YES" if num_group == 1 else "NO")

Solution (Python):
import math



def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    
    return divisors

def ValueToBits(x,digit):
    res = [0 for i in range(digit)]
    now = x
    for i in range(digit):
        res[i]=now%2
        now = now >> 1
    return res

def BitsToValue(arr):
    n = len(arr)
    ans = 0
    for i in range(n):
        ans+= arr[i] * 2**i
    return ans

def ZipArray(a):
    aa = [[a[i],i]for i in range(n)]

    aa.sort(key = lambda x : x[0])
    for i in range(n):
        aa[i][0]=i+1
    aa.sort(key = lambda x : x[1])
    b=[aa[i][0] for i in range(len(a))]
    return b

def ValueToArray10(x, digit):
    ans = [0 for i in range(digit)]
    now = x
    for i in range(digit):
        ans[digit-i-1] = now%10
        now = now //10
    return ans

def Zeros(a,b):
    if(b<=-1):
        return [0 for i in range(a)]
    else:
        return [[0 for i in range(b)] for i in range(a)]

def AddV2(v,w):
    return [v[0]+w[0],v[1]+w[1]]

dir4 = [[1,0],[0,1],[-1,0],[0,-1]]


def clamp(x,y,z):
    return max(y,min(z,x))

class Bit:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)
 
    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s
 
    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i
            

def Zaatsu(a):
    a.sort()
    now = a[0][0]
    od = 0
    for i in range(n):
        if(now==a[i][0]):
            a[i][0]=od
        else:
            now = a[i][0]
            od+=1
            a[i][0] = od
    
    a.sort(key = lambda x : x[1])
    return a

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)


'''
def cmb(n, r, p):
    if (r < 0) or (n < r):
        return 0
    r = min(r, n - r)
    return fact[n] * factinv[r] * factinv[n-r] % p

p = 2
N = 10 ** 6 + 2
fact = [1, 1]  
factinv = [1, 1]  
inv = [0, 1]  

for i in range(2, N + 1):
    fact.append((fact[-1] * i) % p)
    inv.append((-inv[p % i] * (p // i)) % p)
    factinv.append((factinv[-1] * inv[-1]) % p)

'''

def rl(x):
    return range(len(x))













n,m = list(map(int, input().split()))
u = UnionFind(n)

infos = []

humlng = [[] for i in range(m)]

for i in range(n):
    infos.append(list(map(int, input().split())))
    
    k = infos[-1]
    for j in range(1,len(k)):
        humlng[k[j]-1].append(i)

for i in humlng:
    if(len(i)<=1):
        continue
    for j in range(1,len(i)):
        u.union(i[0],i[j])
ans = True
for i in range(n):
    ans = ans and u.same_check(0,i)
    

print("YES" if ans else "NO")

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

N, M = map(int, input().split())
uf = UnionFind(N)
s = [set() for m in range(M+1)]
for i in range(N):
  KL = list(map(int, input().split()))
  for l in KL[1:]:
    s[l].add(i)

for m in range(1, M+1):
  if s[m]:
    u = s[m].pop()
    for v in s[m]:
      uf.union(u, v)

par = [uf.find(i) for i in range(N)]
if min(par) == max(par):
  print('YES')
else:
  print('NO')

Solution (Python):
import math

import queue
from collections import deque,defaultdict
import heapq
from sys import stdin,setrecursionlimit


ipt = stdin.readline
setrecursionlimit(10**7)

def main():
    n,m = map(int,ipt().split())
    ms = [[] for _ in [0]*(m+1)]
    ns = []
    for i in range(n):
        l = [int(i) for i in ipt().split()]
        ns.append(l[1::])
        for j in l[1::]:
            ms[j].append(i)
    q = queue.Queue()
    nal = [-1]*n
    mal = [-1]*(m+1)
    nal[0] = 1
    q.put((0,1))
    while not q.empty():
        qi1,qi2 = q.get()
        if qi2 == 1:
            for i in ns[qi1]:
                if mal[i] == -1:
                    mal[i] = 1
                    q.put((i,2))
        else:
            for i in ms[qi1]:
                if nal[i] == -1:
                    nal[i] = 1
                    q.put((i,1))
    if -1 in nal:
        print("NO")
    else:
        print("YES")

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

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())
    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())
    uf = UnionFind(n)
    la = [None]*m
    for i in range(n):
        a = list(map(int, input().split()))
        for v in a[1:]:
            if la[v-1] is None:
                la[v-1] = i
            else:
                uf.union(i, la[v-1])
    if uf.group_count() == 1:
        print("YES")
    else:
        print("NO")

if __name__ == "__main__":
    main()

Solution (Python):
from scipy.sparse import*
(n,m),*t=[map(int,t.split())for t in open(0)]
*b,a=zip(*[(i,j+n,1)for i,(_,*t)in enumerate(t)for j in t])
print('YNEOS'[1in csgraph.connected_components(csr_matrix((a,b),[n-~m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*;(n,m),*d=[map(int,o.split())for o in open(0)];*w,a=zip(*[(i,j+n-1,1)for i,(_,*d)in enumerate(d)for j in d]);print("YNEOS"[1in csgraph.connected_components(csr_matrix((a,w),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*;(n,m),*d=[map(int,o.split())for o in open(0)];*w,a=zip(*[(i,j+n-1,1)for i,(_,*d)in enumerate(d)for j in d]);print("YNEOS"[1in csgraph.connected_components(csr_matrix(((a,w)),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*;(n,m),*d=[map(int,o.split())for o in open(0)];*w,a=zip(*[(i,j+n-1,1)for i,(_,*d)in enumerate(d)for j in d]);print("YNEOS"[1in csgraph.connected_components(csr_matrix(((a,w)),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*
(n,m),*d=[map(int,o.split())for o in open(0)]
*w,a=zip(*[(i,j+n-1,1)for i,(_,*d)in enumerate(d)for j in d])
print("YNEOS"[1in csgraph.connected_components(csr_matrix(((a,w)),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*
(n,m),*t=[map(int,t.split())for t in open(0)]
a,b,c=zip(*[(i,j+n-1,1)for i,(_,*t)in enumerate(t)for j in t])
print('YNEOS'[1in csgraph.connected_components(csr_matrix(((c,(a,b))),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*
(n,m),*t=[map(int,t.split())for t in open(0)]
a,b,c=zip(*[(i,j+n-1,1)for i,(*t,)in enumerate(t)for j in t[1:]])
print('YNEOS'[1in csgraph.connected_components(csr_matrix(((c,(a,b))),[n+m]*2))[1][:n]::2])

Solution (Python):
from scipy.sparse import*
(n,m),*p=[map(int,t.split())for t in open(0)]
a,b,c=zip(*[(i,j+n-1,1)for i,q in enumerate(p)for j in list(q)[1:]])
print('YNEOS'[1in csgraph.connected_components(csr_matrix(((c,(a,b))),[n+m]*2))[1][:n]::2])

Solution (Python):
from numpy import*;from scipy.sparse import*;(n,m),*p=[map(int,o.split())for o in open(0)];e=array([(i,j+n-1,1)for i,q in enumerate(p)for j in list(q)[1:]]).T;print("YNEOS"[1in csgraph.connected_components(csr_matrix(((e[2],e[:2])),[n+m]*2))[1][:n]::2])

Solution (Python):
from numpy import*
from scipy.sparse import*
(n,m),*p=[map(int,o.split())for o in open(0)]
e=array([(i,j+n-1,1)for i,q in enumerate(p)for j in list(q)[1:]]).T
print("YNEOS"[1in csgraph.connected_components(csr_matrix(((e[2],e[:2])),[n+m]*2))[1][:n]::2])

Solution (Python):
from numpy import*
from scipy.sparse import*
(n,m),*p=[map(int,o.split())for o in open(0)]
e=array([(i,j+n-1,1)for i,q in enumerate(p)for j in list(q)[1:]]).T
print("NO"if 1 in csgraph.connected_components(csr_matrix(((e[2],e[:2])),[n+m]*2))[1][:n]else"YES")

Solution (Python):

class UnionFind():
    def __init__(self,N,M):
        self.N = N
        self.M = M
        self.parents = [-1]*(N + M)

    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 unite(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 same(self,x,y):
        return self.find(x) == self.find(y)
    
    def answer(self):
        r = self.find(0)
        if all(r == self.find(i) for i in range(1,self.N)):
            return True
        else:
            return False

N,M = map(int,input().split())
uf = UnionFind(N,M)
for i in range(N):
    A = list(map(int,input().split()))
    for a in A[1:]:
        uf.unite(i,a - 1 + N)
if uf.answer():
    print('YES')
else:
    print('NO')

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())
    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
sys.setrecursionlimit(10**8)

def main():
    n,m = map(int,input().split())
    UF = UnionFind(n+m)
    for i in range(n):
        kl = list(map(int, input().split()))
        for j in range(1,len(kl)):
            UF.union(i,n+kl[j]-1)
    for i in range(n-1):
        if not UF.same(i,i+1):
            print('NO')
            return
    print('YES')
if __name__ == "__main__":
    main()

Solution (Python):
import sys
import collections

sys.setrecursionlimit(10 ** 8)
ni = lambda: int(sys.stdin.readline())
nm = lambda: map(int, sys.stdin.readline().split())
nl = lambda: list(nm())
ns = lambda: sys.stdin.readline().rstrip()


def solve():
    N, M = nm()
    uf = UnionFind(M)
    lang_spoken = set()
    for i in range(N):
        k, *lang = nm()
        assert len(lang) == k
        roots = {uf.find(l - 1) for l in lang}
        lang_spoken |= roots
        rit = iter(roots)
        x = next(rit)
        for y in rit:
            uf.union(x, y)
    lang1 = next(iter(lang_spoken))
    return uf.size(lang1) == len(lang_spoken)


class UnionFind:
    def __init__(self, n):
        
        self.n = n
        
        self._root_table = list(range(n))
        
        self._size_table = [1] * n

    def find(self, x):
        """Returns x's root node id."""
        r = self._root_table[x]
        if r != x:
            
            r = self._root_table[x] = self.find(r)
        return r

    def union(self, x, y):
        """Merges two groups."""
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        
        if self._size_table[x] < self._size_table[y]:
            x, y = y, x

        self._size_table[x] += self._size_table[y]
        self._root_table[y] = x

    def size(self, x):
        return self._size_table[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._root_table) if x == i]

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


print(["NO", "YES"][solve()])

Solution (Python):
import sys
import collections

sys.setrecursionlimit(10 ** 8)
ni = lambda: int(sys.stdin.readline())
nm = lambda: map(int, sys.stdin.readline().split())
nl = lambda: list(nm())
ns = lambda: sys.stdin.readline().rstrip()


def solve():
    N, M = nm()
    uf = UnionFind(M)
    lang_spoken = set()
    for i in range(N):
        k, *lang = nm()
        assert len(lang) == k
        roots = {uf.find(l - 1) for l in lang}
        lang_spoken |= roots
        roots = list(roots)
        x = roots[0]
        for y in roots[1:]:
            uf.union(x, y)
    lang1 = next(iter(lang_spoken))
    return uf.size(lang1) == len(lang_spoken)


class UnionFind:
    def __init__(self, n):
        
        self.n = n
        
        self._root_table = list(range(n))
        
        self._size_table = [1] * n

    def find(self, x):
        """Returns x's root node id."""
        r = self._root_table[x]
        if r != x:
            
            r = self._root_table[x] = self.find(r)
        return r

    def union(self, x, y):
        """Merges two groups."""
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        
        if self._size_table[x] < self._size_table[y]:
            x, y = y, x

        self._size_table[x] += self._size_table[y]
        self._root_table[y] = x

    def size(self, x):
        return self._size_table[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._root_table) if x == i]

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


print(["NO", "YES"][solve()])

Solution (Python):
import sys
input = lambda: sys.stdin.readline().rstrip()
n, m = map(int, input().split())

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

uf = UnionFind(n+m)
for i in range(n):
    _, *l = list(map(int, input().split()))
    for lang in l:
        uf.union(i, n+lang-1)

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

Solution (Python):
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 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, sys.stdin.readline().strip().split())


langs = [[] for _ in range(M)]
for i in range(N):
    tmp = list(map(int, sys.stdin.readline().strip().split()))
    K = tmp[0]
    L = tmp[1:]
    for l in L:
        langs[l-1].append(i)


uf = UnionFind(N)
for peoples in langs:
    for i in range(len(peoples)-1):
        uf.union(peoples[i], peoples[i+1])


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

Solution (Python):
n, m = map(int, input().split())
tree = [[] for _i in range(m+n+1)]
for i in range(n):
    x = list(map(int, input().split()))
    tree[i].extend([i+n for i in x[1:]])
    for j in x[1:]:
        tree[j+n].append(i)

from collections import deque
q = deque([1])
visit = [0 for _i in range(m+n+2)]
visit[1] = 1
while q:
    p = q.pop()
    for j in tree[p]:
        if visit[j]==0:
            visit[j] = 1
            q.appendleft(j)
if sum(visit[:n]) == n:
    print("YES")
else:
    print("NO")

Solution (Python):
n,m= map(int,input().split())
langdic = {key:[] for key in range(1,m+1)}
for i in range(1,n+1):
    k,*p= map(int,input().split())
    for j in p:langdic[j].append(i)
newlanglist = []
for key in langdic.keys():
    if len(langdic[key])>1:newlanglist.append((langdic[key]))
par = [-1]*(n+1)
def find(x):
    if par[x]<0:return x
    else:
        par[x]=find(par[x])
        return par[x]
def unites2(alist):
    top = min(alist)
    toproot = find(top)
    for a in alist:
        aroot = find(a)
        if top!=a:
            if aroot==toproot:pass
            else:
                grp = par[aroot]
                par[aroot]=toproot
                par[toproot]+=grp
for lis in newlanglist:unites2(lis)
c=0
for t in par[1:]:
    if t<0:c+=1
if c==1:print('YES')
else:print('NO')

Solution (Python):
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]

    N,M = LI()
    g = [i for i in range(0,N+M+1)]
    g_num = [0] + [1 for _ in range(N)] + [0 for _ in range(M)]
    def find(x):
        if g[x] == x: return x
        g[x] = find(g[x])
        return g[x]

    def union(x,y):
        if find(x) == find(y): return
        g_num[g[x]] += g_num[g[y]]
        g_num[g[y]] = 0
        g[g[y]] = g[x]


    for i in range(1,N+1):
        for l in LI()[1:]: union(i,N+l)

    if g_num[N] == N:
        print('YES')
    else:
        print('NO')

if __name__ == '__main__':
    main()

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 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[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 = map(int, input().split())
l = [None] * n
for i in range(n):
    k, *l[i] = list(map(lambda x: int(x) - 1, input().split()))
uf = UnionFind(m)
for row in l:
    for i in range(len(row) - 1):
        uf.unite(row[i], row[i + 1])
s = set()
for row in l:
    for x in row:
        s.add(uf.find(x))
if len(s) == 1:
    print('YES')
else:
    print('NO')

Solution (Python):
import numpy as np;from scipy.sparse import *;l=[];n,m=map(int,input().split())
for i in range(n):
  for j in input().split()[1:]:l.append((i,int(j)+n-1,1))
edge=np.array(l,dtype=np.int64).T;graph=csr_matrix(((edge[2],edge[:2])),(n+m,n+m));_,l=csgraph.connected_components(graph);print("NO"if 1 in l[:n]else"YES")

Solution (Python):
import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import connected_components
import sys
input=sys.stdin.readline

n,m=map(int,input().split())
l=[]
for i in range(n):
    for j in input().split()[1:]:
        l.append((i,int(j)+n-1,1))
edge=np.array(l,dtype=np.int64).T
graph=csr_matrix(((edge[2],edge[:2])),(n+m,n+m))

_,ll=connected_components(graph)

if 1 in ll[:n]:
    print("NO")
else:
    print("YES")