#include<iostream>
#include<queue>
#include<cstring>
#include<map>
using namespace std;
const int maxn = 100;
int p,N,s,t,n,in[maxn][maxn],flow,line;
int ans,num;
int tot,head[maxn];
map<int,int> mp;
struct Edge{
int to,nxt,w,pw;
}e[maxn*maxn];
void add(int u,int v,int w)
{
mp[u*maxn+v] = tot;
e[tot].to = v; e[tot].pw = e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot++;
e[tot].to = u; e[tot].pw = e[tot].w = 0; e[tot].nxt = head[v]; head[v] = tot++;
}
int dep[maxn];
bool bfs()
{
memset(dep,0,sizeof(dep));
queue<int> q; q.push(s); dep[s] = 1;
while(!q.empty())
{
int fa = q.front(); q.pop();
for(int i = head[fa]; ~i; i = e[i].nxt)
{
if(e[i].w && !dep[e[i].to])
dep[e[i].to] = dep[fa]+1, q.push(e[i].to);
}
}
return dep[t];
}
int dfs(int fa,int flow)
{
if(fa == t) return flow;
int res = 0;
for(int i = head[fa]; ~i; i = e[i].nxt)
{
int to = e[i].to , w = e[i].w;
if(w && dep[to] == dep[fa]+1)
{
int d = dfs(to,min(flow,w));
e[i].w -= d; e[i^1].w += d;
flow -= d; res += d;
}
}
if(res == 0) dep[fa] = 0;
return res;
}
void dinic()
{
while(bfs()) flow += dfs(s,0x3f3f3f3f);
}
int main()
{
while(~scanf("%d%d",&p,&N))
{
memset(head,-1,sizeof(head)); tot = 0;
s = 0; t = N + 1; n = N + 2;flow = 0; line = 0;
for(int i = 1; i <= N; ++i)
for(int j = 0; j < 2*p+1; ++j) scanf("%d",&in[i][j]);
bool flag_s,flag_t;
for(int i = 1; i <= N; ++i)
{
flag_s = flag_t = 1;
for(int k =0; k < p; ++k)
{
if(in[i][k+1]==1) flag_s=false;
if(in[i][p+1+k]==0) flag_t=false;
}
if(flag_s) add(s,i,in[i][0]);
if(flag_t) add(i,t,in[i][0]);
bool flag = 1;
for(int j = 1; j <= N; ++j)
{
if(i != j)
{
flag = 1;
for(int k=0;(k<p)&&flag;++k)
if(in[i][p+k+1]+in[j][k+1]==1) flag=false;//接口对不上不连接i和j
if(flag) add(i,j,min(in[i][0],in[j][0]));
}
}
}
dinic();
for(int i = 1; i <= N; ++i)
{
for(int j = head[i]; ~j; j = e[j].nxt)
{
if(e[j].to == t) continue;
int to = e[j].to, w = e[j].w;
if(e[j].pw > e[j].w) line++;
}
}
printf("%d %d\n",flow,line);
for(int i = 1; i <= N; ++i)
{
for(int j = head[i]; ~j; j = e[j].nxt)
{
if(e[j].to == t) continue;
int to = e[j].to, w = e[j].w;
if(e[j].pw > e[j].w) printf("%d %d %d\n",e[j^1].to, e[j].to,e[j].pw - e[j].w);
}
}
}
}
主要是最大路径的打印,由于网络流的特点 最大流是确定的,但是可能存在不同的到达路径,我输出的跟答案是不一样的,一直以为是算法错了,没想到是路径数量统计错了,只有当前流和之前的保存的副本不一样的时候,才路径数量+1