#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 100
#define INF 0xfffffff
int G[maxn+10][maxn+10], CopyG[maxn+10][maxn+10];
int Layer[maxn+10], N, n, p;
bool visit[maxn+10];
struct node{int x, y, c;}q[maxn+10];
void FunIn();
void FunOut();
bool ok(int a[], int b[]);
bool CountLayer();
int Dinic();
bool cmp(node n1, node n2);
int main()
{
while(scanf("%d%d", &p, &n) != EOF)
{
FunIn();
FunOut();
}
return 0;
}
void FunIn()
{
int i, j, a[maxn][20], b[maxn][20], c[maxn+10];
N = 2*n+1;
memset(G, 0, sizeof(G));
memset(CopyG, 0, sizeof(CopyG));
for(i=1; i<=n; i++)
{
scanf("%d", &c[i]);
for(j=0; j<p; j++)
scanf("%d", &a[i][j]);
for(j=0; j<p; j++)
scanf("%d", &b[i][j]);
}
for(i=0; i<p; i++)
a[n+1][i] = 1, b[0][i] = 0;
c[0] = INF;
for(i=0; i<=n; i++)
{
for(j=1; j<=n+1; j++)
{
if(i != j && ok(b[i], a[j]))
{
if(j == n+1)j = N;
if(i == 0)
CopyG[0][j] = G[0][j] = c[i];
else
CopyG[i+n][j] = G[i+n][j] = c[i];
}
else if(i == j)
CopyG[i][i+n] = G[i][i+n] = c[i];
}
}
}
void FunOut()
{
int MaxFlow = Dinic();
int i, j, k=0;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if(i != j && CopyG[i+n][j] > G[i+n][j])
{
q[k].x = i, q[k].y = j;
q[k++].c = CopyG[i+n][j] - G[i+n][j];
}
}
}
sort(q, q+k, cmp);
printf("%d %d
", MaxFlow, k);
for(i=0; i<k; i++)
printf("%d %d %d
", q[i].x, q[i].y, q[i].c);
}
bool ok(int a[], int b[])
{
for(int i=0; i<p; i++)
{
if(a[i] != b[i] && b[i] != 2)
return false;
}
return true;
}
bool CountLayer()
{
deque<int> Q;
memset(Layer, -1, sizeof(Layer));
Layer[0] = 0, Q.push_back(0);
while(Q.size())
{
int v = Q.front();Q.pop_front();
for(int i=1; i<=N; i++)
{
if(G[v][i] && Layer[i] == -1)
{
Layer[i] = Layer[v] + 1;
if(i == N)return true;
else Q.push_back(i);
}
}
}
return false;
}
int Dinic()
{
int MaxFlow = 0, i;
while(CountLayer())
{
deque<int> Q;
memset(visit, false, sizeof(visit));
Q.push_back(0);
while(Q.size())
{
int v = Q.back();
if(v == N)
{
int MinFlow=INF, MinFlow_si, si, ei;
int len = Q.size();
for(i=1; i<len; i++)
{
si = Q[i-1], ei = Q[i];
if(MinFlow > G[si][ei])
{
MinFlow = G[si][ei];
MinFlow_si = si;
}
}
for(i=1; i<len; i++)
{
si = Q[i-1], ei = Q[i];
G[si][ei] -= MinFlow;
G[ei][si] += MinFlow;
}
MaxFlow += MinFlow;
while(Q.size() && Q.back() != MinFlow_si)
{
visit[Q.back()] = false;
Q.pop_back();
}
}
else
{
for(i=1; i<=N; i++)
{
if(G[v][i] && Layer[v]+1 == Layer[i] && !visit[i])
{
visit[i] = true;
Q.push_back(i);
break;
}
}
if(i > N)Q.pop_back();
}
}
}
return MaxFlow;
}
bool cmp(node n1, node n2)
{
return n1.c > n2.c;
}