#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
// upper bound: 2(N-1) (by 2 stars)
constexpr int LIM = 300'010;
int minF[LIM], maxF[LIM];
void init() {
fill(minF, minF + LIM, 1001001001);
fill(maxF, maxF + LIM, -1);
for (int r = 1; ; ++r) {
for (int f = r*(r-1)/2; f < (r+1)*r/2; ++f) {
const int d = f - (r-1);
if (d >= LIM) {
cerr<<"minF = ";pv(minF,minF+20);
cerr<<"maxF = ";pv(maxF,maxF+20);
return;
}
chmin(minF[d], f);
chmax(maxF[d], f);
}
}
}
namespace exper {
// [l, r)^n, increasing
template <class F> void doArraysIncrRec(int n, int l, int r, F f, int i, vector<int> &as) {
if (i == n) {
f(as);
} else {
for (as[i] = i ? as[i - 1] : l; as[i] < r; ++as[i]) doArraysIncrRec(n, l, r, f, i + 1, as);
}
}
template <class F> void doArraysIncr(int n, int l, int r, F f) {
vector<int> as(n);
doArraysIncrRec(n, l, r, f, 0, as);
}
void run() {
constexpr int LIM_K = 5;
constexpr int LIM_N = 10;
for (int K0 = 0; K0 <= LIM_K; ++K0) for (int K1 = 0; K1 <= LIM_K; ++K1) if (K0 + K1 >= 2) {
vector<int> Ms;
for (int N = 2; N <= LIM_N; ++N) {
int minM = 1001001001;
vector<pair<vector<int>, vector<int>>> bests;
doArraysIncr(K0, 0, (N-1) + 1, [&](const vector<int> &E) -> void {
doArraysIncr(K1, 0, N*(N-1)/2 + 1, [&](const vector<int> &F) -> void {
int m = 0;
for (int k = 0; k < K0; ++k) m += E[k];
for (int l = 0; l < K1; ++l) m += F[l];
for (int k = 0; k < K0; ++k) if (m - E[k] < N - 1) return;
for (int l = 0; l < K1; ++l) {
// contract other colors
const int n = max(N - (m - F[l]), 1);
if (F[l] < n*(n-1)/2) return;
}
if (chmin(minM, m)) bests.clear();
if (minM == m) bests.emplace_back(E, F);
});
});
Ms.push_back(minM);
cout << K0 << " " << K1 << " " << N << ": " << minM << endl;
for (const auto &best : bests) cout << " " << best << endl;
}
cerr << K0 << " " << K1 << " " << Ms << endl;
}
/*
0 2 [1, 2, 4, 5, 6, 8, 10, 11, 12]
0 3 [1, 2, 3, 5, 6, 7, 8, 9, 11]
0 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
0 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
1 1 [1, 3, 4, 6, 8, 9, 11, 13, 15]
1 2 [1, 2, 4, 5, 6, 7, 9, 10, 12]
1 3 [1, 2, 3, 5, 6, 7, 8, 9, 10]
1 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
1 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
2 0 [2, 4, 6, 8, 10, 12, 14, 16, 18]
2 1 [1, 3, 4, 5, 7, 8, 10, 11, 12]
2 2 [1, 2, 4, 5, 6, 7, 8, 10, 11]
2 3 [1, 2, 3, 5, 6, 7, 8, 9, 10]
2 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
2 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
3 0 [2, 3, 5, 6, 8, 9, 11, 12, 14]
3 1 [1, 3, 4, 5, 6, 8, 9, 10, 12]
3 2 [1, 2, 4, 5, 6, 7, 8, 9, 11]
3 3 [1, 2, 3, 5, 6, 7, 8, 9, 10]
3 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
3 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
4 0 [2, 3, 4, 6, 7, 8, 10, 11, 12]
4 1 [1, 3, 4, 5, 6, 7, 9, 10, 11]
4 2 [1, 2, 4, 5, 6, 7, 8, 9, 10]
4 3 [1, 2, 3, 5, 6, 7, 8, 9, 10]
4 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
4 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
5 0 [2, 3, 4, 5, 7, 8, 9, 10, 12]
5 1 [1, 3, 4, 5, 6, 7, 8, 10, 11]
5 2 [1, 2, 4, 5, 6, 7, 8, 9, 10]
5 3 [1, 2, 3, 5, 6, 7, 8, 9, 10]
5 4 [1, 2, 3, 4, 6, 7, 8, 9, 10]
5 5 [1, 2, 3, 4, 5, 7, 8, 9, 10]
*/
}
} // exper
/*
c >= 2 ==> star OK
K0 colors with c = 0: E[k] edges
K1 colors with c = 1: F[l] edges
necessary condition to be connected?
contract other colors:
c = 0: 1 point
c = 1: complete
M = \sum[k] E[k] + \sum[l] E[l]
M - E[k] >= N - 1
M - F[l] >= N - R[l], where binom(R[l],2) <= F[l]
M - (N-1) >= E[k]
M - (N-1) >= F[l] - (R[l]-1)
RHS: almost same
colorful paths (only c = 1) from vertex 0,
then create cycles: connect endpoints by colorful paths
*/
struct Solver {
int N, K;
vector<int> C;
int M;
vector<pair<pair<int, int>, int>> edges;
void ae(int u, int v, int k) {
edges.emplace_back(make_pair(u, v), k);
}
void run() {
for (int k = 0; k < K; ++k) if (C[k] >= 2) {
M = N-1;
for (int u = 1; u < N; ++u) ae(0, u, k);
return;
}
vector<int> colorss[2];
for (int k = 0; k < K; ++k) colorss[C[k]].push_back(k);
const int K0 = colorss[0].size();
const int K1 = colorss[1].size();
int minM = 0, maxM = K1;
int maxD = 0;
vector<int> ds(K, 0);
for (; ; ) {
for (int k = 0; k < K; ++k) {
M = max((N-1) + maxD, minM);
if (M <= maxM) goto found;
if (k < K0) {
minM += 1;
maxM += 1;
} else {
minM += (minF[ds[k] + 1] - minF[ds[k]]);
maxM += (maxF[ds[k] + 1] - maxF[ds[k]]);
}
chmax(maxD, ++ds[k]);
}
}
found:{}
vector<int> es(K0), fs(K1), rs(K1);
{
int m = M;
for (int k = 0; k < K0; ++k) m -= es[k] = ds[k];
for (int k = 0; k < K1; ++k) m -= fs[k] = minF[ds[K0 + k]];
for (int k = 0; k < K1; ++k) {
const int d = ds[K0 + k];
const int t = min(m, maxF[d] - minF[d]);
m -= t;
fs[k] += t;
}
assert(m == 0);
}
for (int k = 0; k < K1; ++k) rs[k] = (fs[k] - ds[K0 + k]) + 1;
// cerr<<K0<<" "<<K1<<" "<<N<<": M = "<<1<<", ds = "<<ds<<", es = "<<es<<", fs = "<<fs<<", rs = "<<rs<<endl;
const int maxR = K1 ? *max_element(rs.begin(), rs.end()) : 1;
int n = 1;
vector<int> us(maxR-1, 0);
for (int k = 0; k < K1; ++k) {
for (int i = 0; i < rs[k]-1; ++i) {
const int v = n++;
ae(us[i], v, colorss[1][k]);
us[i] = v;
}
}
auto go = [&](int u, int v) -> void {
int len = 0;
for (int k = 0; k < K; ++k) if (ds[k]) {
--ds[k];
++len;
}
vector<int> path(len + 1);
path[0] = u;
path[len] = v;
for (int k = 1; k < len; ++k) path[k] = n++;
for (int k = 0; k < len; ++k) ae(path[k], path[k + 1], (k < K0) ? colorss[0][k] : colorss[1][k - K0]);
};
for (int i = 0; i < maxR-1; ++i) for (int j = 0; j < i; ++j) {
if (ds[0]) go(us[i], us[j]);
}
for (; ds[0]; ) go(0, 0);
assert(n == N);
}
void judge() {
assert((int)edges.size() == M);
for (const auto &edge : edges) {
const int u = edge.first.first;
const int v = edge.first.second;
const int k = edge.second;
assert(0 <= u); assert(u < N);
assert(0 <= v); assert(v < N);
assert(0 <= k); assert(k < K);
}
for (int kk = 0; kk < K; ++kk) {
vector<vector<int>> d(N, vector<int>(N, N));
for (int u = 0; u < N; ++u) d[u][u] = 0;
for (const auto &edge : edges) {
const int u = edge.first.first;
const int v = edge.first.second;
const int k = edge.second;
chmin(d[u][v], (kk == k) ? 1 : 0);
chmin(d[v][u], (kk == k) ? 1 : 0);
}
for (int w = 0; w < N; ++w) for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) chmin(d[u][v], d[u][w] + d[w][v]);
for (int u = 0; u < N; ++u) for (int v = 0; v < N; ++v) assert(d[u][v] <= C[kk]);
}
}
void input() {
scanf("%d%d", &N, &K);
C.resize(K);
for (int k = 0; k < K; ++k) {
scanf("%d", &C[k]);
}
}
void output() {
printf("%d\n", M);
for (const auto &edge : edges) {
const int u = edge.first.first;
const int v = edge.first.second;
const int k = edge.second;
printf("%d %d %d\n", u + 1, v + 1, k + 1);
}
}
};
void stress() {
constexpr int LIM_K = 10;
constexpr int LIM_N = 20;
for (int K0 = 0; K0 <= LIM_K; ++K0) for (int K1 = 0; K1 <= LIM_K; ++K1) if (K0 + K1 >= 2) {
vector<int> Ms;
for (int N = 2; N <= LIM_N; ++N) {
Solver solver;
solver.N = N;
solver.K = K0 + K1;
for (int k = 0; k < K0; ++k) solver.C.push_back(0);
for (int k = 0; k < K1; ++k) solver.C.push_back(1);
solver.run();
solver.judge();
Ms.push_back(solver.M);
}
cerr << K0 << " " << K1 << " " << Ms << endl;
}
}
int main() {
init();
// exper::run();
// stress();
for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
Solver solver;
solver.input();
solver.run();
solver.output();
#ifdef LOCAL
solver.judge();
#endif
}
#ifndef LOCAL
break;
#endif
}
return 0;
}