#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 10;
int n, m, head[maxn], tot, df, dfn[maxn];
int L, R, ans1, ans2;
struct Edge {
  int u, v, val;
} edge[maxn << 1];
struct Node {
  int to, nxt;
} node[maxn];
vector<int> vec;
void addedge(int u, int v, int w) {
  node[tot].to = v;
  node[tot].nxt = head[u];
  head[u] = tot++;
}
int ind[maxn], vis[maxn];
bool topo() {
  queue<int> q;
  for (int i = 1; i <= n; ++i) {
    if (!ind[i]) q.push(i), dfn[i] = ++df;
  }
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = head[u]; ~i; i = node[i].nxt) {
      int v = node[i].to;
      --ind[v];
      if (!ind[v]) q.push(v), dfn[v] = ++df;
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (!dfn[i]) return false;
  }
  return true;
}
bool check(int len) {
  df = 0;
  memset(dfn, 0, sizeof(dfn));
  tot = 0;
  memset(head, -1, sizeof(head));
  memset(ind, 0, sizeof(ind));
  for (int i = 1; i <= m; ++i) {
    if (edge[i].val > len) {
      addedge(edge[i].u, edge[i].v, edge[i].val);
      ind[edge[i].v]++;
    }
  }
  return topo();
}
int main() {
  scanf("%d%d", &n, &m);
  R = 0;
  L = 0;
  ans2 = 0;
  for (int i = 1; i <= m; ++i)
    scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].val),
        R = max(R, edge[i].val);
  while (L <= R) {
    int mid = (L + R) >> 1;
    if (check(mid))
      ans1 = mid, R = mid - 1;
    else
      L = mid + 1;
  }
  check(ans1);
  for (int i = 1; i <= m; ++i) {
    if (dfn[edge[i].u] > dfn[edge[i].v]) ans2++, vec.push_back(i);
  }
  printf("%d %d\n", ans1, ans2);
  sort(vec.begin(), vec.end());
  for (int i = 0, len = vec.size(); i < len; ++i)
    printf("%d%c", vec[i], i == len - 1 ? '\n' : ' ');
  return 0;
}
