#line 1 "b.cpp"
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(int)a;i<(int)b;i++)
#define all(p) p.begin(),p.end()
using ll = long long;
template<class T> bool chmin(T &a, T b){return (a > b ? a = b, 1 : 0);}
template<class T> bool chmax(T &a, T b){return (a < b ? a = b, 1 : 0);}
#include <atcoder/maxflow>
void solve(){
int N, M;
cin >> N >> M;
vector X(M, vector<ll>(N + 1));
rep(i, 0, M) rep(j, 0, N){
cin >> X[i][j];
X[i][N] += X[i][j];
}
sort(all(X), [&](vector<ll> l, vector<ll> r){
return l.back() < r.back();
});
ll g = 0;
if (X[0].back() == X.back().back()){
rep(i, 0, N){
cout << i + 1;
cout << (i == N - 1 ? "\n" : " ");
}
return;
}
rep(i, 0, M - 1) g = gcd(g, X[i + 1].back() - X[i].back());
vector<ll> Z(M - 1);
rep(i, 0, M - 1) Z[i] = (X[i + 1].back() - X[i].back()) / g;
atcoder::mf_graph<int> G(N * 2 + 2);
int S = N * 2;
int T = S + 1;
rep(i, 0, N) G.add_edge(S, i, 1), G.add_edge(i + N, T, 1);
rep(i, 0, N) rep(j, 0, N){
ll diff = X[1][j] - X[0][i];
if (diff < 0 || diff % Z[0]) continue;
diff /= Z[0];
ll tmp = X[1][j];
bool ok = 1;
rep(k, 2, M){
tmp += diff * Z[k - 1];
int b = lower_bound(X[k].begin(), X[k].end() - 1, tmp) - X[k].begin();
if (b >= N || X[k][b] != tmp){
ok = 0;
break;
}
}
if (ok) G.add_edge(i, j + N, 1);
}
int f = G.flow(S, T);
assert(f == N);
auto E = G.edges();
vector<ll> u(N);
for (auto e : E){
if (e.flow == 1 && e.from < N){
u[e.from] = X[1][e.to - N] - X[0][e.from];
}
}
vector<int> order(N), ans(N);
rep(i, 0, N) order[i] = i;
sort(all(order), [&](int l, int r){
if (u[l] != u[r]) return u[l] < u[r];
return l < r;
});
rep(i, 0, N) ans[order[i]] = i + 1;
rep(i, 0, N){
if (i) cout << " ";
cout << ans[i];
}
cout << "\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
}
/*
test
3
2 4
1 2
3 4
5 6
7 8
1 2
1
1
3 4
1 2 3
6 9 9
10 15 17
12 18 21
*/