#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e5 + 1;
int n, m, weight[MAX], dis[MAX];
bool avail[MAX];
pair<int, int> trace[MAX];
struct node {
  int x, y, z;
  node(int x, int y, int z) : x(x), y(y), z(z) {}
};
vector<node> edge;
vector<node> adj[MAX];
vector<node> res;
queue<int> que;
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int x, y, z;
    cin >> x >> y >> z;
    edge.push_back(node(x, y, z));
    adj[x].push_back(node(y, z, i));
    adj[y].push_back(node(x, z, i));
  }
  dis[1] = 1;
  que.push(1);
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (int i = 0; i < adj[u].size(); ++i)
      if (!dis[adj[u][i].x]) {
        dis[adj[u][i].x] = dis[u] + 1;
        que.push(adj[u][i].x);
      }
  }
  que.push(1);
  trace[1].first = -1;
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (int i = 0; i < adj[u].size(); ++i)
      if (dis[adj[u][i].x] == dis[u] + 1)
        if (!trace[adj[u][i].x].first) {
          trace[adj[u][i].x] = pair<int, int>(u, adj[u][i].z);
          que.push(adj[u][i].x);
          weight[adj[u][i].x] = weight[u] + adj[u][i].y;
        } else if (weight[adj[u][i].x] < weight[u] + adj[u][i].y) {
          weight[adj[u][i].x] = weight[u] + adj[u][i].y;
          trace[adj[u][i].x] = pair<int, int>(u, adj[u][i].z);
        }
  }
  memset(avail, true, m * sizeof(bool));
  do {
    avail[trace[n].second] = false;
    if (!edge[trace[n].second].z) {
      res.push_back(edge[trace[n].second]);
    }
    n = trace[n].first;
  } while (n != 1);
  for (int i = 0; i < m; ++i)
    if (avail[i] && edge[i].z) res.push_back(edge[i]);
  cout << res.size() << endl;
  for (int i = 0; i < res.size(); ++i)
    cout << res[i].x << ' ' << res[i].y << ' ' << 1 - res[i].z << endl;
  return 0;
}
