#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
using namespace std;
#define M 1001
typedef struct Tree
{
int data;
struct Tree *lson,*rson;
} TNode,*ListTree;
ListTree built(int n)
{
int val;
ListTree point[M];
memset(point,NULL,sizeof(point));
for(int i=1; i<=n; i++)
{
scanf("%d",&val);
point[i]=(ListTree)malloc(sizeof(TNode));
point[i]->data=val;
point[i]->lson=NULL;
point[i]->rson=NULL;
}
for(int i=1; i<=n; i++)
{
int k;
scanf("%d",&k);
for(int j=0; j<k; j++)
{
int tmp;
scanf("%d",&tmp);
if(j==0)
point[i]->lson=point[tmp];
if(j==1)
point[i]->rson=point[tmp];
}
}
return point[1];
}
void output(ListTree root)//前序遍历
{
if(root!=NULL)
{
cout<<root->data<<" ";
output(root->lson);
output(root->rson);
}
}
bool judge(ListTree ra,ListTree rb)//验证rb是不是ra的子树
{
if(rb==NULL)
return true;
if(ra==NULL)
return false;
if(ra->data!=rb->data)
return false;
return judge(ra->lson,rb->lson)&&judge(ra->rson,rb->rson);
}
bool solve(ListTree ra,ListTree rb)//在ra中与rb根节点相同
{
bool ans=false;
if(ra!=NULL&&rb!=NULL)
{
if(ra->data==rb->data)
ans=judge(ra,rb);
if(!ans)
ans=solve(ra->lson,rb);
if(!ans)
ans=solve(ra->rson,rb);
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
ListTree roota=built(n);
ListTree rootb=built(m);
if(m==0)
{
printf("NO\n");
continue;
}
bool result=solve(roota,rootb);
if(result)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}