#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 5;
int n, m, ans;
int num[MAX_N];
pair<int, pair<int, int> > edge[MAX_N];
bool MARK[MAX_N];
int upd[MAX_N];
int UPD[MAX_N];
int dis[MAX_N];
vector<pair<int, pair<int, int> > > G[MAX_N];
int Arr[MAX_N + MAX_N];
int L, R;
int K[MAX_N];
vector<pair<int, pair<int, int> > > EDGE;
bool cmp(int a1, int a2) { return dis[a1] < dis[a2]; }
void bfs(int v) {
  memset(dis, 127, sizeof dis);
  dis[v] = 0;
  Arr[R++] = v;
  while (L < R) {
    int u = Arr[L++];
    for (int i = 0; i < G[u].size(); i++)
      if (1 + dis[u] < dis[G[u][i].first]) {
        dis[G[u][i].first] = 1 + dis[u];
        Arr[R++] = G[u][i].first;
      }
  }
  for (int i = 0; i < n; i++) K[i] = i;
  memset(num, -1, sizeof num);
  sort(K, K + n, cmp);
  for (int i = 0; i < n; i++) {
    int u = K[i];
    for (int j = 0; j < G[u].size(); j++)
      if (dis[u] + 1 == dis[G[u][j].first] &&
          num[G[u][j].first] <= num[u] + G[u][j].second.first) {
        num[G[u][j].first] = num[u] + G[u][j].second.first;
        upd[G[u][j].first] = G[u][j].second.second;
        UPD[G[u][j].first] = u;
      }
  }
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int v, u, w;
    cin >> v >> u >> w;
    edge[i] = {v, {u, w}};
    v--;
    u--;
    G[v].push_back({u, {w, i}});
    G[u].push_back({v, {w, i}});
  }
  bfs(0);
  int ind = n - 1;
  while (ind) {
    MARK[upd[ind]] = true;
    ind = UPD[ind];
  }
  for (int i = 0; i < m; i++) {
    if ((MARK[i] && !edge[i].second.second) ||
        (!MARK[i] && edge[i].second.second)) {
      ans++;
      EDGE.push_back(
          {edge[i].first, {edge[i].second.first, !edge[i].second.second}});
    }
  }
  cout << ans << "\n";
  for (int i = 0; i < EDGE.size(); i++)
    cout << EDGE[i].first << " " << EDGE[i].second.first << " "
         << EDGE[i].second.second << "\n";
}
