#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define all(arr) (arr).begin(), (arr).end()
#define ll long long
#define ld long double
#define pb push_back
#define sz(x) int((x).size())
#define fi first
#define se second
#define endl '\n'

const int N = 4e5 + 10;

vector<int> g[N], tg[N], newg[N];

int used[N], bad[N], ans[N], self[N], comp[N], cycle[N], compans[N];

void dfs1(int v){
  used[v] = 1;
  for (auto u : g[v]){
    if (used[u]) bad[u] = 1;
    else dfs1(u);
  }
}

void dfs2(int v){
  used[v] = 1;
  bad[v] = 1;
  for (auto u : g[v]){
    if (!used[u]) dfs2(u);
  }
}

vector<int> topsort;

void dfs3(int v){
  used[v] = 1;
  for (auto u : g[v]){
    if (!used[u]) dfs3(u);
  }
  topsort.pb(v);
}

int cnt = 0;

void dfs4(int v, int cnum){
  used[v] = 1;
  cnt++;
  comp[v] = cnum;
  for (auto u : tg[v]){
    if (!used[u]) dfs4(u, cnum);
  }
}

void dfs5(int v){
  used[v] = 1;
  compans[v] = -1;
  for (auto u : newg[v]){
    if (!used[u]) dfs5(u);
  }
}

void solve(){
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++){
    int a, b;
    cin >> a >> b;
    g[a].pb(b);
    tg[b].pb(a);
    if (a == b) self[a] = 1;
  }
  dfs1(1);
  vector<int> badv, reached(n + 10), rep(n + 10);
  for (int i = 1; i <= n; i++){
    if (used[i]) reached[i] = 1;
    if (bad[i]) badv.pb(i);
  }
  for (int i = 0; i <= n; i++) used[i] = 0;
  for (auto u : badv){
    if (!used[u]) dfs2(u);
  }
  for (int i = 0; i <= n; i++) used[i] = 0;
  for (int i = 1; i <= n; i++){
    if (!used[i]) dfs3(i);
  }
  reverse(all(topsort));
  for (int i = 0; i <= n; i++) used[i] = 0;
  int cnum = 1;
  for (auto i : topsort){
    if (!used[i]){
      cnt = 0;
      dfs4(i, cnum);
      rep[cnum] = i;
      if (cnt > 1 || self[i]) cycle[cnum] = 1;
      cnum++;
    }
  }
  for (int i = 1; i <= n; i++){
    for (auto u : g[i]) newg[comp[i]].pb(comp[u]);
  }
  for (int i = 0; i <= n; i++) used[i] = 0;
  for (int i = 1; i <= n; i++){
    if (cycle[i] && !used[i] && reached[rep[i]]) dfs5(i);
  }
  for (int i = 1; i <= n; i++){
    if (!reached[i]) continue;
    if (compans[comp[i]] == -1){
      ans[i] = -1;
    }
    else{
      if (bad[i]) ans[i] = 2;
      else ans[i] = 1;
    }
  }
  for (int i = 1; i <= n; i++) cout << ans[i] << " ";
  cout << endl;
  topsort.clear(); cnt = 0;
  for (int i = 1; i <= n; i++){
    g[i].clear();
    tg[i].clear();
    newg[i].clear();
    used[i] = bad[i] = ans[i] = self[i] = comp[i] = cycle[i] = compans[i] = 0;
  }
}

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  // cout.precision(20);
  int t;
  cin >> t;
  while (t--){
    solve();
  }
}