#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX_N = 100005;
const int MAX_V = 600005; // Rozmiar grafu: Drzewo przedziałowe (~262k) + Pomiary (200k)
int N, S_wells, M;
int fixed_depth[MAX_N];
int S; // Rozmiar drzewa przedziałowego (potęga 2)
vector<int> adj[MAX_V];
int in_degree[MAX_V];
long long dp[MAX_V];
// Funkcja dodająca krawędzie z przedziałów [A, B] do wierzchołka pomocniczego U
void add_range_edges(int A, int B, int U) {
A += S - 1;
B += S - 1;
while (A <= B) {
if (A % 2 == 1) { // A to prawe dziecko, dodajemy całe i przechodzimy w prawo
adj[A].push_back(U);
in_degree[U]++;
A++;
}
if (B % 2 == 0) { // B to lewe dziecko, dodajemy całe i przechodzimy w lewo
adj[B].push_back(U);
in_degree[U]++;
B--;
}
A /= 2;
B /= 2;
}
}
int main() {
// Optymalizacja operacji wejścia/wyjścia (niezbędne w tym zadaniu!)
ios_base::sync_with_stdio(false);
cin.tie(NULL);
if (!(cin >> N >> S_wells >> M)) return 0;
for (int i = 0; i < S_wells; ++i) {
int p, d;
cin >> p >> d;
fixed_depth[p] = d;
}
// Wyznaczanie potęgi 2 pod rozmiar drzewa
S = 1;
while (S < N) S *= 2;
// Budowanie szkieletu drzewa przedziałowego (krawędzie: dziecko -> rodzic)
for (int i = 1; i < S; ++i) {
adj[2 * i].push_back(i);
in_degree[i]++;
adj[2 * i + 1].push_back(i);
in_degree[i]++;
}
// Odczytywanie pomiarów i budowanie zależności
for (int i = 0; i < M; ++i) {
int U = 2 * S + i; // Index sztucznego wierzchołka reprezentującego ten pomiar
int L, R, K;
cin >> L >> R >> K;
vector<int> X(K);
for (int j = 0; j < K; ++j) {
cin >> X[j];
}
// 1. Zależności typu: Wszystko z wykluczeniem punktów X -> U
int curr = L;
for (int j = 0; j < K; ++j) {
int x = X[j];
if (curr <= x - 1) {
add_range_edges(curr, x - 1, U);
}
curr = x + 1;
}
if (curr <= R) {
add_range_edges(curr, R, U);
}
// 2. Zależności typu: U -> punkty X
for (int j = 0; j < K; ++j) {
int x = X[j];
int leaf_x = S + x - 1;
adj[U].push_back(leaf_x);
in_degree[leaf_x]++;
}
}
// Ile wierzchołków grafu realnie używamy
int total_nodes = 2 * S + M - 1;
queue<int> Q;
// Inicjalizacja pod sortowanie topologiczne
for (int i = 1; i <= total_nodes; ++i) {
if (in_degree[i] == 0) {
Q.push(i);
}
// Minimalna wartość dla danego miejsca
if (i >= S && i < S + N) {
int orig_idx = i - S + 1;
dp[i] = fixed_depth[orig_idx] ? fixed_depth[orig_idx] : 1;
} else {
dp[i] = 0;
}
}
int visited_count = 0;
vector<int> topo_order;
topo_order.reserve(total_nodes);
// Sortowanie topologiczne (Algorytm Kahna)
while (!Q.empty()) {
int u = Q.front();
Q.pop();
visited_count++;
topo_order.push_back(u);
for (int v : adj[u]) {
in_degree[v]--;
if (in_degree[v] == 0) {
Q.push(v);
}
}
}
// Wykryto cykl zależności = sytuacja niemożliwa
if (visited_count < total_nodes) {
cout << "NIE\n";
return 0;
}
// Aktualizacja głębokości (najdłuższe ścieżki w DAG)
for (int u : topo_order) {
// Wszystkie krawędzie wychodzące z wierzchołków pomiarów wymuszają +1 do głębokości
int w = (u >= 2 * S) ? 1 : 0;
for (int v : adj[u]) {
dp[v] = max(dp[v], dp[u] + w);
}
}
// Walidacja warunków krytycznych zadania
for (int i = 1; i <= N; ++i) {
int leaf = S + i - 1;
if (dp[leaf] > 1000000000LL) {
cout << "NIE\n";
return 0;
}
if (fixed_depth[i] != 0 && dp[leaf] > fixed_depth[i]) {
cout << "NIE\n";
return 0;
}
}
// Wyjście
cout << "TAK\n";
for (int i = 1; i <= N; ++i) {
cout << dp[S + i - 1] << (i == N ? "" : " ");
}
cout << "\n";
return 0;
}