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):
class UnionFind(object):
    def __init__(self, N):
        self.parent = [-1] * N 
    
    

    
    def root(self, A):
        if self.parent[A-1] < 0: 
            return A
        self.parent[A-1] = self.root(self.parent[A-1]) 
        return self.parent[A-1] 

    
    def size(self, A):
        return -1 * self.parent[self.root(A)-1]

    
    def connect(self, A, B):
        A = self.root(A) 
        B = self.root(B) 
        if A == B: 
            return False
        
        
        if self.size(A) < self.size(B): 
            A, B = B, A
        
        self.parent[A-1] += self.parent[B-1] 
        self.parent[B-1] = A 
        return True
    
    def same(self, A, B):
        if self.root(A) == self.root(B):
            return True
        else:
            return False
            












import sys
input = sys.stdin.readline

N, M = map(int, input().split())
L1 = []
L1_append = L1.append

uni = UnionFind(M + 1)
for _ in range(N):
    KL = list(map(int ,input().split()))
    tmp = KL[1]
    L1_append(tmp)
    for i in KL[2:]:
        uni.connect(tmp, i)

tmp = uni.root(L1[0])
for i in L1[1:]:
    if tmp != uni.root(i):
        print ('NO')
        exit()

print ('YES')

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

stdin = sys.stdin

ri = lambda: int(rs())
rl = lambda: list(map(int, stdin.readline().split()))  
rs = lambda: stdin.readline().rstrip()  


N, M = rl()
KL = [rl() for _ in range(N)]
speak_lan = [[] for _ in range(M+1)] 
for i, x in enumerate(KL):
    k, *lan = x
    for l in lan:
        speak_lan[l].append(i)

communicate = set()
used_language = set()
def dfs(person):
    global communicate
    global used_language
    lan = KL[person][1:]
    for l in lan:
        if l in used_language:
            continue
        used_language.add(l)
        for p in speak_lan[l]:
            if p not in communicate:
                communicate.add(p)
                dfs(p)

dfs(0)
if len(communicate) == N:
    print('YES')
else:
    print('NO')

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

root = [i for i in range(M + 1)]
comp_size = [1] * (M + 1)

def root_find(x):
  y = root[x]
  if y == x:
    return x
  else:
    z = root_find(y)
    root[x] = z
    return z

def merge(x, y):
  rx = root_find(x)
  ry = root_find(y)
  sx = comp_size[x]
  sy = comp_size[y]
  if sx >= sy:
    root[ry] = rx
    comp_size[rx] = sx + sy
  else:
    root[rx] = ry
    comp_size[ry] = sx + sy

for l in L:
  for i in range(len(l) - 1):
    merge(l[i], l[i + 1])


r = root_find(L[0][0])
for i in range(1, N):
  if r != root_find(L[i][0]):
    print("NO")
    exit()

print("YES")

Solution (Python):
n,m = map(int, input().split())
a = [list(map(int, input().split())) for i in range(n)]
lang = [[] for i in range(m+1)]
graph = [[] for i in range(n+1)]
for i in range(n):
    for j in range(1,a[i][0]+1):
        lang[a[i][j]].append(i+1)
for i in range(m+1):
    if len(lang[i]) > 1:
        for j in range(len(lang[i])-1):
            graph[lang[i][j+1]].append(lang[i][j])
            graph[lang[i][j]].append(lang[i][j+1])
stack = [1]
visited = [0]*(n+1)
while stack:
    x = stack.pop()
    visited[x] = 1
    for y in graph[x]:
        if visited[y] == 1:
            continue
        stack.append(y)
if 0 not in visited[1:]:
    print("YES")
else:
    print("NO")

Solution (Python):
import sys

class UnionFind():
	def __init__(self, n):
		self.n = n
		self.root = [-1] * (n + 1)
		self.rank = [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 0
		elif self.rank[x] > self.rank[y]:
			self.root[x] += self.root[y]
			self.root[y] = x
		else:
			self.root[y] += self.root[x]
			self.root[x] = y
			if self.rank[x] == self.rank[y]:
				self.rank[y] += 1

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

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

def main():
	input = sys.stdin.buffer.readline
	n, m = map(int, input().split())
	lang = [[] for _ in range(m)]
	uf = UnionFind(n)
	for i in range(n):
		k, *ls = map(int, input().split())
		for l in ls:
			lang[l - 1].append(i)
	for speakers in lang:
		for x, y in zip(speakers, speakers[1:]):
			uf.unite(x, y)
	print("YES" if uf.size(0) == n else "NO")

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

n, m = map(int, input().split())
L = [[] for _ in range(m)]
for i in range(n):
  k, *l = map(int, input().split())
  for j in l:
    L[j-1].append(i)

uf = UnionFind(n)
for i in L:
  for j in range(len(i)-1):
    uf.union(i[j], i[j+1])
if uf.group_count() == 1:
  print("YES")
else:
  print("NO")

Solution (Python):
def examA():
    H, W = LI()
    S = [LSI() for _ in range(H)]
    Alpha = [chr(ord('A') + i) for i in range(26)]
    for i in range(H):
        for j in range(W):
            if S[i][j]=="snuke":
                ans = str(Alpha[j]) + str(i+1)
    print(ans)
    return

def examB():
    N = I()
    ans = []
    cur = int((N*2-1)**0.5)+1
    ansC = (cur+1)*cur//2
    neg = ansC-N
    if neg>cur:
        cur -=1
        ansC = (cur + 1) * cur // 2
        neg = ansC - N
    for i in range(1,cur+1):
        if i!=neg:
            ans.append(i)
    for v in ans:
        print(v)

    return

def bfs(n,e,fordfs):
    
    que = deque()
    que.append(e)
    len = [10**9]*n
    len[e] = 0
    while que:
        now = que.popleft()
        nowlen = len[now]
        for ne in fordfs[now]:
            if len[ne] == 10**9:
                len[ne] = nowlen+1
                que.append(ne)
    return len
def examC():
    N, M = LI()
    V = [[]for _ in range(N+M)]
    for i in range(N):
        L = LI()
        for k in range(1,L[0]+1):
            V[i].append(L[k]+N-1)
            V[L[k]+N-1].append(i)
    length = bfs(N+M,0,V)
    ans = "YES"
    for i in length[:N]:
        if i==10**9:
            ans = "NO"
    print(ans)
    return

import sys,copy,bisect,itertools,heapq,math
from heapq import heappop,heappush,heapify
from collections import Counter,defaultdict,deque
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))
def LSI(): return list(map(str,sys.stdin.readline().split()))
def LS(): return sys.stdin.readline().split()
def SI(): return sys.stdin.readline().strip()
mod = 10**9 + 7
inf = float('inf')

if __name__ == '__main__':
    examC()

Solution (Python):
N,M = map(int,input().split())
K = []
L = []
for _ in range(N):
    k,*l = map(int,input().split())
    K.append(k)
    L.append(l)
    
graph = [[] for _ in range(N+M)]
for i in range(N):
    for l in L[i]:
        graph[i].append(N+l-1)
        graph[N+l-1].append(i)

visited = [0 for _ in range(N+M)]
visited[0] = 1
stack = [0]

while stack:
    node = stack.pop()
    for adj in graph[node]:
        if not visited[adj]:
            visited[adj] = 1
            stack.append(adj)
            
print('YES' if all(visited[:N]) else 'NO')

Solution (Python):
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda:sys.stdin.readline().rstrip()
def resolve():
    n,m=map(int,input().split())
    
    E=[[] for _ in range(n+m)]
    for i in range(n):
        L=list(map(lambda x:int(x)-1,input().split()))[::-1]
        L.pop()
        for l in L:
            E[i].append(n+l)
            E[n+l].append(i)

    
    used=[0]*(n+m)
    used[0]=1
    Q=[0]
    while(Q):
        v=Q.pop()
        for nv in E[v]:
            if(used[nv]): continue
            used[nv]=1
            Q.append(nv)

    print("YES" if(min(used[:n])==1) else "NO")
resolve()

Solution (Python):
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda:sys.stdin.readline().rstrip()

class UnionFind(object):
    def __init__(self,n):
        self.__par=list(range(n))
        self.__rank=[0]*n
        self.__size=[1]*n

    def root(self,k):
        if(self.__par[k]==k): return k
        self.__par[k]=self.root(self.__par[k])
        return self.__par[k]

    def unite(self,i,j):
        i=self.root(i); j=self.root(j)
        par=self.__par; rank=self.__rank; size=self.__size
        if(i==j): return False
        if(rank[i]>rank[j]):
            par[j]=i
            size[i]+=size[j]
        else:
            par[i]=j
            size[j]+=size[i]
            if(rank[i]==rank[j]): rank[j]+=1
        return True

    def is_same(self,i,j):
        return self.root(i)==self.root(j)

    def size(self,k):
        return self.__size[self.root(k)]

def resolve():
    n,m=map(int,input().split())
    uf=UnionFind(m)
    S=set()
    for _ in range(n):
        L=list(map(int,input().split()))[::-1]
        k=L.pop()
        for i in range(k):
            S.add(L[i]-1)
            if(i+1<k):
                uf.unite(L[i]-1,L[i+1]-1)

    print("YES" if(max(uf.size(i) for i in range(m))==len(S)) else "NO")
resolve()

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


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

uf = UnionFind(M+1)
talker = [False]*(M+1)

for i in range(N):
    K, *L = map(int, input().split())
    f = -1
    for l in L:
        talker[l] = True
        if f == -1:
            f = l
        else:
            uf.Unite(f, l)

for m in range(M+1):
    if talker[m] is True:
        if not uf.isSameGroup(f, m):
            print('NO')
            exit()
print('YES')

Solution (Python):

from collections import defaultdict,deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

def solve():
    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 rank[x] < rank[y]:
            par[x] = y
        else:
            par[y] = x
            if rank[x] == rank[y]:
                rank[x] += 1

    n,m = LI()
    N = n+m
    par = [i for i in range(N)]
    rank = [0]*N
    for i in range(n):
        l = LI()
        for j in l[1:]:
            unite(j-1,i+m)
    r = set([root(i) for i in range(m,N)])
    if len(r) == 1:
        print("YES")
    else:
        print("NO")
    return



if __name__ == "__main__":
    solve()

Solution (Python):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**5)

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

visited = [False] * (N + M)
visited[0] = True
q = [0]

while q :
    cur = q.pop()
    for nex in v[cur] :
        if not visited[nex] :
            q.append(nex)
            visited[nex] = True

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

Solution (Python):

import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1


def read_int():
    return int(input())


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


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


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


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


@mt
def slv(N, M, L):
    l2p = defaultdict(set)
    p2l = defaultdict(set)
    for i, l in enumerate(L):
        p2l[i+1] = set(l)
        for j in l:
            l2p[j].add(i+1)
    
    
    q = [1]
    p_done = set(q)
    l_done = set()
    while q:
        p = q.pop()
        for l in p2l[p]:
            if l in l_done:
                continue
            l_done.add(l)
            for p2 in l2p[l]:
                if p2 in p_done:
                    continue
                p_done.add(p2)
                q.append(p2)
    return 'YES' if set(range(1, N+1)) == p_done else 'NO'



def main():
    N, M = read_int_n()
    L = [read_int_n()[1:] for _ in range(N)]
    print(slv(N, M, L))


if __name__ == '__main__':
    main()

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline


class UnionFind:
    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.size = [1 for _ in range(N)]

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

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

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

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


N, M = map(int, input().split())
Un = UnionFind(N)  
D = defaultdict(lambda: [])
for i in range(N):
    _, *L = map(lambda x: int(x)-1, input().split())
    for l in L:
        D[l].append(i)
for i in range(M):
    if len(D[i]) > 1:
        t = D[i]
        for d in t[1:]:
            Un.union(t[0], d)
print("YES" if Un.connectedNum(0) == N else "NO")

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline


class UnionFind:
    """
    sizeによる実装
    """

    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.size = [1 for _ in range(N)]

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

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

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

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


N, M = map(int, input().split())
Un = UnionFind(N)  
D = defaultdict(lambda: [])
for i in range(N):
    _, *L = map(lambda x: int(x)-1, input().split())
    for l in L:
        D[l].append(i)
for i in range(M):
    if len(D[i]) > 1:
        t = D[i]
        for d in t[1:]:
            Un.union(t[0], d)
if Un.size[Un.find(0)] == N:
    print("YES")
else:
    print("NO")

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline


class UnionFind:
    """
    sizeによる実装
    """

    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.size = [1 for _ in range(N)]

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

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

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

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


N, M = map(int, input().split())
Un = UnionFind(N)  
D = defaultdict(lambda: [])
for i in range(N):
    _, *L = map(lambda x: int(x)-1, input().split())
    for l in L:
        D[l].append(i)
for i in range(M):
    if len(D[i]) > 1:
        t = D[i]
        for d in t[1:]:
            Un.union(t[0], d)
if Un.size[Un.find(0)] == N:
    print("YES")
else:
    print("NO")

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)

    def ans(self):
        return (len(set(self.par))-1)

n,m=map(int,input().split())
uf=UnionFind(n)
l=[[] for i in range(m)]
for i in range(n):
    k=list(map(int,input().split()))
    k=k[1:]
    for j in k:
        l[j-1].append(1+i)
    
for i in range(m):
    if len(l[i])>0:
        ll=l[i][0]
        for j in range(len(l[i])-1):
            uf.union(ll,l[i][j+1])

for i in range(1,n+1):
    uf.find(i)

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

Solution (Python):
import sys
input = sys.stdin.buffer.readline
N, M = map(int, input().split())
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)]
uf = UnionFind(N + M)
for i in range(N):
  l = list(map(int, input().split()))
  for j in range(1, l[0] + 1):
    uf.Unite(i + 1, l[j] + N)
p = -1
for i in range(1, N + 1):
  if uf.Find_Root(i) == i and p == -1:
    p = i
  elif p == -1:
    p = uf.Find_Root(i)
  elif uf.Find_Root(i) != p:
    p = -1
    break
  elif uf.Find_Root(i) == -1 and p != -1:
    p = -1
    break
if p == -1:
  print("NO")
else:
  print("YES")

Solution (Python):

def find(x):
    if par[x] < 0:
        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 False
    else:
        
        if par[x] > par[y]:
            x,y = y,x
        par[x] += par[y]
        par[y] = x
        return True


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


def size(x):
    return -par[find(x)]

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


par = [-1]*n
lan = [[] for _ in [0]*m]
for pt in range(n):
    l = tuple(map(int,input().split()))
    for i in range(1,len(l)):
        lan[l[i]-1].append(pt)

for i in range(m):
    for j in range(1,len(lan[i])):
        unite(lan[i][0],lan[i][j])

cnt = 0
for e in par:
    if e < 0:
        cnt += 1

if cnt == 1:
    print('YES')
else:
    print('NO')

Solution (Python):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 9)

N,M = map(int,input().split())
L = []
for i in range(N):
  tmp = list(map(int,input().split()))
  L.append(tmp[1:])



E = [set() for _ in range(N+M)]
for i in range(N):
  for l in L[i]:
    E[i].add(l+N-1)
    E[l+N-1].add(i)



Visited = [0 for _ in range(N+M)]
def dfs(v):
  Visited[v] = 1
  for u in E[v]:
    if Visited[u] == 0:
      dfs(u)
dfs(0)
print('YES' if sum(Visited[:N]) == N else 'NO')

Solution (Python):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 9)

N,M = map(int,input().split())
L = []
for i in range(N):
  tmp = list(map(int,input().split()))
  L.append(tmp[1:])



E = [set() for _ in range(N+M)]
for i in range(N):
  for l in L[i]:
    E[i].add(l+N-1)
    E[l+N-1].add(i)



Visited = [0 for _ in range(N+M)]
def dfs(v):
  Visited[v] = 1
  for u in E[v]:
    if Visited[u] == 0:
      dfs(u)
dfs(0)
print('YES' if sum(Visited[:N]) == N else 'NO')

Solution (Python):
import sys
def input():
    return sys.stdin.readline()[:-1]
inf=float("inf")
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 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]:
            self.par[x] = y
        else:
            self.par[y] = x
            
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

n,m=map(int,input().split())
kl=[list(map(int,input().split())) for i in range(n)]
uf=UnionFind(m)
for i in range(n):
    for j in range(2,kl[i][0]+1):    
        uf.union(kl[i][1], kl[i][j])

for i in range(1,n):
    if not uf.same_check(kl[0][1],kl[i][1]):
        print("NO")
        quit()
print("YES")

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


ad = [[] for _ in range(N+M)]

for i in range(N):
    for l in L[i]:
        l -= 1
        ad[i].append((l+N, 1))
        ad[l+N].append((i, 1))

from heapq import heappush, heappop
inf = float('inf')



def dijkstra(start,ad):
    global dist
    
    N = len(ad)
    dist = [inf] * N
    dist[start] = 0
    
    
    pq = [(dist[start], start)]
    while pq:
        dist_v, v = heappop(pq)
        for nv, nw in ad[v]:
            if dist[nv] > dist_v + nw:
                dist[nv] = dist_v + nw
                heappush(pq,(dist[nv], nv))
            
                
                

dijkstra(0, ad)

for i in range(N):
    if dist[i] == inf:
        print("NO")
        exit()

print("YES")

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

lang = [[] for _ in range(M)]

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

class Unionfind:

    __slots__ = ['nodes','size']

    def __init__(self, n):
        self.nodes = list(range(n))
        self.size = [1]*n

    def root(self, x):
        if self.nodes[x] == x:
            return x
        else:
            root_x = self.root(self.nodes[x])
            self.nodes[x] = root_x
            return root_x

    def unite(self, x, y):
        x = self.root(x); y = self.root(y)
        if x == y:
            return
        if self.size[x] < self.size[y]:
            x, y = y, x
        self.size[x] += self.size[y]
        self.nodes[y] = x

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

    def kind(self):
        for v in range(N):
            self.root(v)
        return len(list(set(self.nodes)))

uf = Unionfind(N)

for group in lang:
    for i in range(len(group)-1):
        v = group[i]
        nv = group[i+1]
        uf.unite(v, nv)

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

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


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

    
    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 groupsize(self):
        self.cnt = 0
        for i,x in enumerate(self.par):
            if x == i:
                self.cnt += 1
        return self.cnt

    
    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.par[x] = y
            self.root[x] += self.root[y]
            self.root[y] = self.root[x]
        else:
            self.par[y] = x
            self.root[x] += self.root[y]
            self.root[y] = self.root[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 count(self, x):
        return -self.root[self.find(x)]
    
    
uf = UnionFind(M)
for lk in L:
    l = lk[1:]
    if len(l) > 0:
        base = l[0]-1
        for i in range(1,len(l)):
            uf.union(base,l[i]-1)
            
isUsed = [False] * M
for lk in L:
    for l in lk[1:]:
        isUsed[l-1] = True


looplist = [i for i in range(M) if isUsed[i]]
tmp1 = looplist[0]
for i in looplist[1:]:
    if not(uf.same_check(tmp1,i)):
        print('NO')
        break
else:
    print('YES')

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


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

    
    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 groupsize(self):
        self.cnt = 0
        for i,x in enumerate(self.par):
            if x == i:
                self.cnt += 1
        return self.cnt

    
    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.par[x] = y
            self.root[x] += self.root[y]
            self.root[y] = self.root[x]
        else:
            self.par[y] = x
            self.root[x] += self.root[y]
            self.root[y] = self.root[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 count(self, x):
        return -self.root[self.find(x)]
    
    
uf = UnionFind(M)
for lk in L:
    l = lk[1:]
    if len(l) > 0:
        base = l[0]-1
        for i in range(1,len(l)):
            uf.union(base,l[i]-1)
            
isUsed = [False] * M
for lk in L:
    for l in lk[1:]:
        isUsed[l-1] = True


looplist = [i for i in range(M) if isUsed[i]]
tmp1 = looplist[0]
for i in looplist[1:]:
    if not(uf.same_check(tmp1,i)):
        print('NO')
        break
else:
    print('YES')