#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 6;
const int INF = 2e9;
vector<pair<int, int> > g[MAXN];
pair<int, int> d[MAXN];
int par[MAXN];
int n, m;
struct str {
  int dist, cnt0;
  int node;
  bool operator<(str const& other) const {
    if (dist != other.dist) return dist > other.dist;
    if (cnt0 != other.cnt0) return cnt0 > other.cnt0;
    return node > other.node;
  }
};
void dijkstra() {
  for (int i = 2; i <= n; i++) d[i] = {INF, INF};
  d[1] = {0, 0};
  priority_queue<str> q;
  q.push({0, 0, 1});
  while (!q.empty()) {
    str u = q.top();
    q.pop();
    for (auto v : g[u.node]) {
      int dist = u.dist + 1;
      int cnt0 = u.cnt0 + (v.second == 0);
      if (make_pair(dist, cnt0) < d[v.first]) {
        d[v.first] = {dist, cnt0};
        q.push({dist, cnt0, v.first});
        par[v.first] = u.node;
      }
    }
  }
}
set<pair<int, int> > inpath;
vector<pair<pair<int, int>, int> > edges;
int main() {
  int br0 = 0, br1 = 0;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int x, y, z;
    cin >> x >> y >> z;
    g[x].push_back({y, z});
    g[y].push_back({x, z});
    if (z == 0)
      br0++;
    else
      br1++;
    edges.push_back({{x, y}, z});
  }
  dijkstra();
  cout << d[n].second + br1 - d[n].first + d[n].second << endl;
  int t1 = n;
  while (par[t1] != 0) {
    inpath.insert({t1, par[t1]});
    inpath.insert({par[t1], t1});
    t1 = par[t1];
  }
  for (int i = 0; i < edges.size(); i++) {
    if (inpath.find(edges[i].first) != inpath.end() && edges[i].second == 0) {
      cout << edges[i].first.first << " " << edges[i].first.second << " "
           << 1 - edges[i].second << endl;
    }
    if (inpath.find(edges[i].first) == inpath.end() && edges[i].second == 1) {
      cout << edges[i].first.first << " " << edges[i].first.second << " "
           << 1 - edges[i].second << endl;
    }
  }
  return 0;
}
