// another fine solution by misof
#include <vector>
#include <iostream>
#include <map>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/biconnected_components.hpp>
#include <boost/graph/adjacency_list.hpp>
using namespace boost;
using namespace std;
  
typedef 
  adjacency_list < vecS, vecS, undirectedS > 
  graph_t;

typedef 
  graph_traits < graph_t >::edge_descriptor 
  edge_t;

typedef 
  graph_traits < graph_t >::edge_iterator
  edge_iter_t;

struct order_edges 
  { bool operator()(const edge_t& x, const edge_t& y) const { return x.get_property() < y.get_property(); }};

typedef 
  map < edge_t, int, order_edges > 
  edge_map;

// V contains a list of edges of a biconnected component
// print() relabels the vertices in V to 0..(N-1) for some N, and prints the graph
void print(const graph_t &G, const vector<edge_t> &V, edge_map &LO, edge_map &HI) {
  int N = 0;
  map<int,int> new_label;
  for (unsigned i=0; i<V.size(); i++) if (!new_label.count(source(V[i],G))) new_label[source(V[i],G)]=N++;
  for (unsigned i=0; i<V.size(); i++) if (!new_label.count(target(V[i],G))) new_label[target(V[i],G)]=N++;
  cout << N << " " << V.size() << endl;
  for (unsigned i=0; i<V.size(); i++)
    cout << new_label[ source(V[i],G) ] << " " << new_label[ target(V[i],G) ] << " " << LO[V[i]] << " " << HI[V[i]] << endl;
}

int main() {
  int T;
  cin >> T;
  cout << T << "\n";

  while (T--) {
    int N, M;
    cin >> N >> M;
    
    graph_t G(N);
    edge_map LO, HI, bicmp_map;

    while (M--) {
      int x,y,a,b;
      cin >> x >> y >> a >> b;
      if (x>y) swap(x,y);

      pair<edge_t,bool> desc = add_edge(x,y,G);
      LO[desc.first]=a; HI[desc.first]=b;
    }

    // if the input graph is not connected, output -1 directly
    vector<int> component_id(num_vertices(G));
    int num = connected_components(G, &component_id[0]);
    if (num > 1) { cout << "-1" << endl; continue; }

    // compute biconnected components
    associative_property_map<edge_map> bimap(bicmp_map);
    size_t num_comps = biconnected_components(G,bimap);
   
    // split the edges of G into components
    vector< vector<edge_t> > V(num_comps);
    edge_iter_t ei, ei_end;
    for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) 
      V[ bimap[*ei] ].push_back( *ei );

    // output each component separately
    cout << num_comps << endl;
    for (size_t i=0; i<num_comps; i++) print( G, V[i], LO, HI );
  }
  return 0;
}

