import sys
import collections
from heapq import heappop, heappush

inputs = sys.stdin.readlines()
cases = int(inputs.pop(0).rstrip())

''' 
Sample Input: 

3
2 2
1 1
1 2
3 3
1 2 3
2 3 1
3 1 2
4 4
'''

### CODE BELOW ###

def getNextPairs(adjMatrix, pair, cols):
  pair = list(pair)
  if len(pair) != 1:
    return [frozenset((adjMatrix[pair[0] - 1][col], adjMatrix[pair[1] - 1][col])) for col in range(cols)]
  else:
    return [frozenset([adjMatrix[pair[0] - 1][col]]) for col in range(cols)]

matrices = []
for _ in range(cases):
  adjMatrix = []
  rowCols = inputs.pop(0).rstrip().split()
  rows = int(rowCols[0])
  cols = int(rowCols[1])
  # this might be wrong, should test this
  
  q = collections.deque()
  visited = set()

  edges = {}
  for r in range(rows):
    adjMatrix.append([int(i) for i in inputs.pop(0).split()])

  for r in range(rows):
    for i in range(r, rows):
      currPair = frozenset((r + 1, i + 1))
      nextPairs = getNextPairs(adjMatrix, currPair, cols)
      for nextPair in nextPairs:
        if nextPair in edges:
          edges[nextPair].add(currPair)
        else:
          edges[nextPair] = set()
          edges[nextPair].add(currPair)
      if i == r:
        q.append(currPair)
        visited.add(currPair)
  print(edges)
  correct = False
  visited = set()
  while q:
    currState = q.pop()
    for nextState in edges[currState]:
      if nextState not in visited:
        visited.add(nextState)
        q.append(nextState)
      if len(visited) == ((rows * (rows - 1)) / 2 + rows): # all possible combos; rows choose 2 + rows choose 1
        correct = True
        break
    if correct == True:
      break
  print("YES" if correct else "NO") 
by