Bracelet Crossings

USACO 2021 December Contest, Gold - Problem 3

Algorithm

Conditions to check:

Python

def solve(n, case):
    active = [0]*(n+1)
    # 0 => not seen, 1 => seen, 2 ==> previously seen
    orders = []
    contain = [-1]*(n+1)
    for sweep in case:
        stack = []
        seen = [0]*(n+1)
        curr_order = []
        for color in sweep:
            if seen[color]:
                if stack[-1] == color:
                    stack.pop()
                else:
                    #print("stack fail")
                    return False # Invalid stack
            else:
                if contain[color] != -1:
                    if contain[color] == 0:
                        if len(stack) != 0:
                            #print("contain fail")
                            return False # Invalid containment
                    elif len(stack) == 0 or stack[-1] != contain[color]:
                        #print("contain fail")
                        return False # Invalid containment
                if len(stack):
                    contain[color] = stack[-1]
                else:
                    contain[color] = 0                
                stack.append(color)
                curr_order.append(color)
            seen[color] = 1
            if active[color] == 0:
                active[color] = 1
            elif active[color] == 2:
                #print("continuity fail",active)
                return False # Not contiguous
        for i in range(n+1):
            if active[i] == 1:
                if seen[i] == 0:
                    active[i] = 2
        # Test ordering
        for order in orders:
            if len(order) == 0:
                continue
            j = 0
            for color in order:
                if color in curr_order:
                    k = curr_order.index(color)
                    if k < j:
                        #print("order fail")
                        return False
                    j = k
        orders.append(curr_order)

    return True

t = int(input())
res = []
for i in range(t):
    input()
    n, m = map(int,input().split())
    case = []
    for _ in range(m):
        case.append(list(map(int,input().split()))[1:])
    res.append(["NO","YES"][solve(n, case)])
for i in res:print(i)