#include<bits/stdc++.h>
using namespace std ;
#define F first
#define S second
#define g0 get<0>
#define g1 get<1>
#define g2 get<2>
#define g3 get<3>
const int N = 505 ;
const int W = 1e6+5 ;
int n , w , arr[N][N][2] , maxi[N][N] , mini[N][N] ;
vector<tuple<int,int,int>> vt[2] , ans ;
vector<pair<int,int>> nei[N][2] ;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) ;
cin >> n >> w ;
for(int l=1 ; l>=0 ; l--){
for(int i=1 ; i<n ; i++){
for(int j=0 ; j<i ; j++){
cin >> arr[i][j][l] ;
}
}
}
memset(mini,0x3f,sizeof(mini)) ;
for(int i=1 ; i<n ; i++){
for(int j=0 ; j<i ; j++){
if(w-arr[i][j][1]<=arr[i][j][0]){
ans.push_back({i,j,arr[i][j][0]}) , ans.push_back({i,j,w-arr[i][j][1]}) ;
maxi[i][j]=maxi[j][i]=max(arr[i][j][0],w-arr[i][j][1]) ;
mini[i][j]=mini[j][i]=min(arr[i][j][0],w-arr[i][j][1]) ;
}
}
}
// build minimum spanning tree in vt[0] and maximum spanning tree in vt[1]
for(int l=0 ; l<n ; l++){
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<n ; j++){
maxi[i][j]=max(maxi[i][j],min(maxi[i][l],maxi[l][j])) ;
mini[i][j]=min(mini[i][j],max(mini[i][l],mini[l][j])) ;
}
}
}
bool flag = ans.size()<=2023 ;
for(int i=1 ; i<n ; i++){
for(int j=0 ; j<i ; j++){
if(arr[i][j][0]!=maxi[i][j] || w-arr[i][j][1]!=mini[i][j]) flag = false ;
}
}
if(!flag){
cout << "NO\n" ;
return 0 ;
}
cout << ans.size() << '\n' ;
for(int i=0 ; i<ans.size() ; i++) cout << g0(ans[i]) << ' ' << g1(ans[i]) << ' ' << g2(ans[i]) << '\n' ;
return 0 ;
}