#pragma comment (linker, "/STACK:30000000")

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>

using namespace std;

#define inpfile "rail.in"
#define outfile "rail.out"

const int NMAX = 100005;
const int MMAX = 100005;
const int KMAX = 100005;

struct Edge {
	int x, y;
};

struct Span {
	int n;
	int rev;
};

struct Node {
	int n, train;
	int rev;
};

struct ENode {
	int x, next, n;
};

vector<Span> paths[KMAX];
vector<Node> nodes;
vector<Edge> edges;
int queue[MMAX];
int s = 0, t = 0;
int sign[MMAX];
bool gone[KMAX];
int n, m, k;

int a[NMAX];
ENode p[2*MMAX];
int minn = 1;
bool u[NMAX];
int res[NMAX];

void Init()
{
	freopen(inpfile, "r", stdin);
	freopen(outfile, "w", stdout);
}

void Out(bool ok)
{
	if (ok)
	{
		printf("YES\n");
		for (int i = 1; i <= n; i++)
			printf("%d ", res[i] - minn + 1);
	} else
		printf("NO\n");
	exit(0);
}

void Swap(int &q, int &w)
{
	int bak = q;
	q = w;
	w = bak;
}

bool EdgeLess(Edge edge1, Edge edge2)
{
	return (edge1.x < edge2.x) || (edge1.x == edge2.x) && (edge1.y < edge2.y);
}

bool NodeLess(Node node1, Node node2)
{
	return node1.n < node2.n;
}

void Inp()
{
	scanf("%d %d", &n, &m);
	edges.resize(m);

	for (int i = 0; i < m; i++)
	{
		scanf("%d %d", &edges[i].x, &edges[i].y);
		if (edges[i].x > edges[i].y)
			Swap(edges[i].x, edges[i].y);
	}

	sort(edges.begin(), edges.end(), EdgeLess);

	Span span;
	Edge edge;
	Node node;
	int x, y;
	
	scanf("%d", &k);
	for (int i = 0; i < k; i++)
	{
		scanf("%d", &x);
		for (scanf("%d", &y); y != 0; x = y, scanf("%d", &y))
		{
			edge.x = x;
			edge.y = y;
			if (edge.x > edge.y)
			{
				Swap(edge.x, edge.y);
				span.rev = 1;
			} else
				span.rev = 0;

			span.n = (int)(lower_bound(edges.begin(), edges.end(), edge, EdgeLess) - edges.begin());
			paths[i].push_back(span);

			node.n = span.n;
			node.train = i;
			node.rev = span.rev;
			nodes.push_back(node);
		}
	}

	sort(nodes.begin(), nodes.end(), NodeLess);
}

void Start(int train, int rev)
{
	for (int i = 0; i < (int)paths[train].size(); i++)
	{
		int j = paths[train][i].n;
		int signj = (paths[train][i].rev + rev) & 1;

		if ((sign[j] != 2) && (sign[j] != signj)) Out(false);
		if (sign[j] == 2)
		{
			sign[j] = signj;
			queue[t] = j;
			t++;
		}
	}

	gone[train] = true;
}

int Rev(int x, int y)
{
	if (x < y) return 0;
	else return 1;
}

void Dfs(int x, int num)
{
	if (u[x]) return;
	u[x] = true;
	res[x] = num;
	if (num < minn)
		minn = num;

	for (int i = a[x]; i; i = p[i].next)
		if ((1 & (sign[p[i].n] + Rev(x, p[i].x))) == 0)
			Dfs(p[i].x, num + 1);
		else 
			Dfs(p[i].x, num - 1);
}

void Solve()
{
	pair< vector<Node>::iterator, vector<Node>::iterator > range;
	
	Node node;
	node.rev = false;
	node.train = 0;

	memset(gone, 0, sizeof(gone));
	for (int i = 0; i < m; i++)
		sign[i] = 2;

	for (int i = 0 ; i < m; i++)
		if (sign[i] == 2)
		{
			sign[i] = 0;
			queue[t] = i; 
			t++;
			
			for (; s < t; s++)
			{
				node.n = queue[s];
				range = equal_range(nodes.begin(), nodes.end(), node, NodeLess);
				for (vector<Node>::iterator it = range.first; it != range.second; it++)
					if (!gone[it->train])
						Start(it->train, (it->rev + sign[node.n]) & 1);
			}

		}

	int x, y;
	memset(a, 0, sizeof(a));
	memset(p, 0, sizeof(p));
	for (int i = 0; i < m; i++)
	{
		x = edges[i].x;
		y = edges[i].y;

		p[i + 1].x = y;
		p[i + 1].n = i;
		p[i + 1].next = a[x];
		a[x] = i + 1;

		p[i + m + 1].x = x;
		p[i + m + 1].n = i;
		p[i + m + 1].next = a[y];
		a[y] = i + m + 1;
	}

	memset(u, 0, sizeof(u));
	for (int i = 1; i <= n; i++)
		if (!u[i])
			Dfs(i, 1);
}

int main()
{
	Init();
	Inp();
	Solve();
	Out(true);
	return 0;
}
