#include <bits/stdc++.h>
using namespace std;
template <typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;
const int inf = 2e9 + 5;
const long long l_inf = 2e18 + 5;
const int mod_v = 1e9 + 7;
const int max_n = 1e5 + 5;
template <typename T>
T gcd(T a, T b) {
  while (b) {
    T temp = a % b;
    a = b;
    b = temp;
  }
  return a;
}
template <typename T>
tuple<T, T, T> egcd(T a, T b) {
  T x1 = 1, x2 = 0, y1 = 0, y2 = 1;
  while (b) {
    T q = a / b, r = a % b;
    T new_x = x1 - q * x2, new_y = y1 - q * y2;
    x1 = x2, y1 = y2, x2 = new_x, y2 = new_y;
    a = b, b = r;
  }
  return make_tuple(a, x1, y1);
}
inline long long lcm(long long a, long long b) { return a * b / gcd(a, b); }
template <typename T>
inline T mod(T a, T b = mod_v) {
  return (a % b + b) % b;
}
template <typename T>
inline T mod_inv(T a, T b = mod_v) {
  return mod(get<1>(egcd(a, b)), b);
}
template <typename T>
inline T sum(T a, T b, T m = mod_v) {
  return mod(mod(a, m) + mod(b, m), m);
}
template <typename T>
inline T difference(T a, T b, T m = mod_v) {
  return mod(mod(a, m) - mod(b, m), m);
}
inline long long product(long long a, long long b, long long m = mod_v) {
  return mod(mod(a, m) * mod(b, m), m);
}
inline long long quotient(long long a, long long b, long long m = mod_v) {
  return mod(mod(a, m) * mod_inv(b, m), m);
}
template <typename T, typename T2>
ostream &operator<<(ostream &s, const pair<T, T2> &p) {
  return s << p.first << ' ' << p.second << ' ';
}
template <typename T, typename T2>
istream &operator>>(istream &s, pair<T, T2> &p) {
  return s >> p.first >> p.second;
}
template <typename T>
ostream &operator<<(ostream &s, const vector<T> &v) {
  for (auto it : v) s << it << ' ';
  return s;
}
template <typename T>
istream &operator>>(istream &s, vector<T> &v) {
  for (auto it = (v).begin(), it_ = (v).end(); it != it_; ++it) s >> *it;
  return s;
}
template <typename T>
void read_range(T beg, T end) {
  while (beg != end) cin >> *beg++;
}
template <typename T>
void print_range(T beg, T end) {
  while (beg != end) cout << *beg++ << ' ';
}
struct reader {
  template <typename T>
  reader &operator,(T &v) {
    cin >> v;
    return *this;
  }
} rdr;
struct debugger {
  template <typename T>
  debugger &operator,(const T &v) {
    cerr << v << ", ";
    return *this;
  }
} dbg;
set<tuple<int, int, int>> edge;
map<pair<int, int>, bool> seen;
vector<tuple<int, int, int>> res;
vector<pair<int, int>> adj[max_n];
pair<int, int> parent[max_n];
pair<int, int> d[max_n];
int n;
void bfs(int s = 1) {
  fill(d + 1, d + 1 + n, make_pair(inf / 2, inf / 2));
  queue<int> q;
  d[s] = make_pair(0, 0);
  q.push(s);
  while (!q.empty()) {
    int u = q.front();
    int one = d[u].first, zero = d[u].second;
    q.pop();
    for (auto &a : adj[u]) {
      int v = a.first, r = a.second;
      int new_zero = zero + (r == 0);
      if (one + zero + 1 < d[v].first + d[v].second or
          (one + zero + 1 == d[v].first + d[v].second and
           new_zero < d[v].second)) {
        int new_one = one + (r == 1);
        d[v] = make_pair(new_one, new_zero);
        q.push(v);
        parent[v] = make_pair(u, r);
      }
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin >> n;
  int m;
  rdr, m;
  ;
  for (int i = 0, i_ = (m); i < i_; ++i) {
    int u, v, r;
    rdr, u, v, r;
    ;
    adj[u].emplace_back(v, r);
    adj[v].emplace_back(u, r);
    edge.emplace(u, v, r);
    edge.emplace(v, u, r);
  }
  bfs();
  int u = n, v, r;
  while (u != 1) {
    v = parent[u].first, r = parent[u].second;
    edge.erase(edge.find(make_tuple(u, v, r)));
    edge.erase(edge.find(make_tuple(v, u, r)));
    if (r == 0) res.emplace_back(u, v, 1);
    u = v;
  }
  for (auto &e : edge) {
    tie(u, v, r) = e;
    if (!seen[make_pair(u, v)] and r == 1) {
      res.emplace_back(u, v, 0);
      seen[make_pair(u, v)] = true;
      seen[make_pair(v, u)] = true;
    }
  }
  cout << res.size() << '\n';
  for (auto &e : res) {
    tie(u, v, r) = e;
    cout << u << ' ' << v << ' ' << r << '\n';
  }
  return 0;
}
