#include <iostream>
#include <vector>
#include <string>
#include <bitset>
#include <queue>
using namespace std;
const int MAXN = 2005;
// Używamy tablicy bitsetów dla szybkiej operacji XOR na wierszach macierzy sąsiedztwa
bitset<MAXN> adj[MAXN];
int state[MAXN]; // 0 lub 1
bool processed[MAXN]; // Czy węzeł został już "usunięty" (przełączony)
int main() {
// Optymalizacja wejścia/wyjścia
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
if (!(cin >> n >> m)) return 0;
string s;
cin >> s;
// Kolejka do przechowywania węzłów, które trzeba przełączyć (stan 1)
queue<int> q;
for(int i = 0; i < n; ++i) {
state[i] = s[i] - '0';
if (state[i] == 1) {
q.push(i);
}
processed[i] = false;
}
for(int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
--u; --v;
adj[u][v] = 1;
adj[v][u] = 1;
}
vector<int> result;
result.reserve(n);
while(!q.empty()) {
int u = q.front();
q.pop();
// Jeśli węzeł był już przetworzony (mógł trafić do kolejki wielokrotnie), pomijamy go
if (processed[u]) continue;
processed[u] = true;
result.push_back(u + 1);
// Iterujemy po wszystkich sąsiadach u
// Ponieważ u jest usuwane, musimy zaktualizować wszystkich jego sąsiadów
for (int v = 0; v < n; ++v) {
if (u != v && adj[u][v] && !processed[v]) {
// 1. Zmiana stanu sąsiada (0->1 lub 1->0)
state[v] ^= 1;
if (state[v] == 1) {
q.push(v);
}
// 2. Aktualizacja krawędzi (lokalne uzupełnienie)
// Dla każdego sąsiada v węzła u, krawędzie między v a innymi sąsiadami u są odwracane.
// Operacja XOR na bitsecie robi to hurtowo.
adj[v] ^= adj[u];
// Czyścimy bity, które mogły zostać błędnie ustawione:
// a) v nie może mieć krawędzi do samego siebie
adj[v][v] = 0;
// b) Połączenie z u jest już nieistotne (u jest processed),
// ale dla porządku bitsetu można je wyzerować (choć check !processed[v] to załatwia)
adj[v][u] = 0;
}
}
}
// Weryfikacja końcowa
// Po zakończeniu procesu wszystkie nieprzetworzone węzły muszą być wyregulowane (0)
// i nie mogą mieć żadnych krawędzi.
bool possible = true;
for(int i = 0; i < n; ++i) {
if (!processed[i]) {
if (state[i] == 1) {
possible = false;
break;
}
// Sprawdzamy, czy zostały jakiekolwiek krawędzie do innych nieprzetworzonych węzłów
for (int j = 0; j < n; ++j) {
if (!processed[j] && adj[i][j]) {
possible = false;
break;
}
}
if (!possible) break;
}
}
if (possible) {
cout << "TAK\n";
cout << result.size() << "\n";
for (size_t i = 0; i < result.size(); ++i) {
cout << result[i] << (i == result.size() - 1 ? "" : " ");
}
cout << "\n";
} else {
cout << "NIE\n";
}
return 0;
}