#include <bits/stdc++.h>
using namespace std;
struct Node {
  int i;
  int dist1 = -1, dist2 = -1, goodroads = -1;
  vector<pair<Node *, pair<bool, int>>> nexts;
};
int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  vector<Node> nodes(n);
  vector<bool> edge_used(m);
  int broken = 0;
  for (int i = 0; i < m; i++) {
    int x, y;
    int z;
    scanf("%d %d %d", &x, &y, &z);
    x--, y--;
    broken += z;
    nodes[x].nexts.push_back({&nodes[y], {z, i}});
    nodes[y].nexts.push_back({&nodes[x], {z, i}});
  }
  for (int i = 0; i < n; i++) nodes[i].i = i;
  queue<Node *> bfs;
  nodes.front().dist1 = 0;
  bfs.push(&nodes.front());
  while (bfs.size()) {
    Node *currnode = bfs.front();
    bfs.pop();
    for (auto &edge : currnode->nexts) {
      if (edge.first->dist1 != -1) continue;
      edge.first->dist1 = currnode->dist1 + 1;
      bfs.push(edge.first);
    }
  }
  nodes.back().dist2 = 0;
  bfs.push(&nodes.back());
  while (bfs.size()) {
    Node *currnode = bfs.front();
    bfs.pop();
    for (auto &edge : currnode->nexts) {
      if (edge.first->dist2 != -1) continue;
      edge.first->dist2 = currnode->dist2 + 1;
      bfs.push(edge.first);
    }
  }
  nodes.front().goodroads = 0;
  bfs.push(&nodes.front());
  while (bfs.size()) {
    Node *currnode = bfs.front();
    bfs.pop();
    for (auto &edge : currnode->nexts) {
      if (currnode->dist1 + edge.first->dist2 + 1 != nodes.back().dist1)
        continue;
      if (edge.first->goodroads == -1) bfs.push(edge.first);
      edge.first->goodroads =
          max(edge.first->goodroads, currnode->goodroads + edge.second.first);
    }
  }
  bfs.push(&nodes.back());
  while (bfs.size()) {
    Node *currnode = bfs.front();
    bfs.pop();
    if (currnode->i == 0) {
      assert(!bfs.size());
      break;
    }
    int max_goodroads = -1;
    pair<Node *, pair<bool, int>> sourceedge;
    for (auto &edge : currnode->nexts) {
      if (currnode->dist2 + edge.first->dist1 + 1 != nodes.back().dist1)
        continue;
      if (edge.first->goodroads == -1) continue;
      if (edge.first->goodroads + edge.second.first > max_goodroads) {
        max_goodroads = edge.first->goodroads + edge.second.first;
        sourceedge = *&edge;
      }
    }
    edge_used[sourceedge.second.second] = true;
    bfs.push(sourceedge.first);
  }
  vector<tuple<int, int, bool>> toprint;
  for (Node &node : nodes) {
    for (auto &edge : node.nexts) {
      if (node.i > edge.first->i) continue;
      if (edge.second.first == edge_used[edge.second.second]) continue;
      toprint.push_back(
          make_tuple(node.i + 1, edge.first->i + 1, !edge.second.first));
    }
  }
  assert(toprint.size() ==
         broken + nodes.back().dist1 - 2 * nodes.back().goodroads);
  printf("%d\n", toprint.size());
  for (auto t : toprint) {
    printf("%d %d %d\n", get<0>(t), get<1>(t), get<2>(t));
  }
  return 0;
}
