#include <bits/stdc++.h>
using namespace std;
vector<pair<int, pair<int, int> > > v[100005];
vector<int> ans;
int n;
bool has_cycle(int mid) {
  int indeg[100005];
  int cnt = 0, x;
  memset(indeg, 0, sizeof(indeg));
  for (int i = 1; i <= n; ++i) {
    for (auto g : v[i]) {
      if (g.second.first > mid) {
        indeg[g.first]++;
      }
    }
  }
  queue<int> q;
  for (int i = 1; i <= n; ++i) {
    if (indeg[i] == 0) {
      q.push(i);
    }
  }
  while (!q.empty()) {
    x = q.front();
    cnt++;
    q.pop();
    for (auto g : v[x]) {
      if (g.second.first > mid) {
        indeg[g.first]--;
        if (indeg[g.first] == 0) q.push(g.first);
      }
    }
  }
  if (cnt == n)
    return false;
  else
    return true;
}
void topological_sort(int res) {
  int indeg[100005];
  int cnt = 0, x;
  memset(indeg, 0, sizeof(indeg));
  for (int i = 1; i <= n; ++i) {
    for (auto g : v[i]) {
      if (g.second.first > res) {
        indeg[g.first]++;
      }
    }
  }
  queue<int> q;
  bool vis[100005];
  memset(vis, false, sizeof(vis));
  for (int i = 1; i <= n; ++i) {
    if (indeg[i] == 0) q.push(i);
  }
  while (!q.empty()) {
    x = q.front();
    vis[x] = true;
    q.pop();
    for (auto g : v[x]) {
      if (g.second.first > res) {
        indeg[g.first]--;
        if (indeg[g.first] == 0) q.push(g.first);
      } else {
        if (vis[g.first] == true) {
          ans.push_back(g.second.second);
        }
      }
    }
  }
}
bool check(int mid) {
  if (has_cycle(mid))
    return false;
  else
    return true;
}
int binary_search() {
  int lo = 0, hi = 1e9;
  while (hi - lo > 1) {
    int mid = (lo + hi) / 2;
    if (check(mid))
      hi = mid;
    else
      lo = mid;
  }
  if (check(lo)) return lo;
  return hi;
}
int main() {
  int m, x, y, c, res;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> x >> y >> c;
    v[x].push_back({y, {c, i}});
  }
  res = binary_search();
  topological_sort(res);
  cout << res << " " << (int)ans.size() << "\n";
  for (auto g : ans) cout << g << " ";
}
