#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
const long long INF = std::numeric_limits<long long>::max();
const int MX = 100101;
const long double PI =
    3.14159265358979323846264338327950288419716939937510582097494L;
template <typename T>
pair<T, T> operator+(const pair<T, T> &a, const pair<T, T> &b) {
  return pair<T, T>(a.first + b.first, a.second + b.second);
}
template <typename T>
pair<T, T> operator-(const pair<T, T> &a, const pair<T, T> &b) {
  return pair<T, T>(a.first - b.first, a.second - b.second);
}
template <typename T>
T operator*(const pair<T, T> &a, const pair<T, T> &b) {
  return (a.first * b.first + a.second * b.second);
}
template <typename T>
T operator^(const pair<T, T> &a, const pair<T, T> &b) {
  return (a.first * b.second - a.second * b.first);
}
template <typename T>
void print(vector<T> vec, string name = "") {
  cout << name;
  for (auto u : vec) cout << u << ' ';
  cout << '\n';
}
vector<long long> sz;
vector<int> p;
int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
void unionSet(int i, int j) {
  if (isSameSet(i, j)) return;
  int first = findSet(i), second = findSet(j);
  if (sz[first] > sz[second])
    p[second] = first, sz[first] += sz[second];
  else {
    p[first] = second;
    sz[second] += sz[first];
  }
}
struct edge {
  int a, b, w, i;
};
long long ats = 0;
set<int> kas;
long long viso = 0;
void getsz(int v, int prev, const vector<vector<edge>> &edges) {
  viso += sz[v];
  for (auto ed : edges[v])
    if ((ed.a == v ? ed.b : ed.a) != prev)
      getsz((ed.a == v ? ed.b : ed.a), v, edges);
}
long long dfs(int v, const vector<vector<edge>> &edges, vector<bool> &visited) {
  visited[v] = true;
  long long curr = sz[v];
  for (auto ed : edges[v]) {
    int nxt = (ed.a == v ? ed.b : ed.a);
    if (visited[nxt]) continue;
    long long kit = dfs(nxt, edges, visited);
    long long naujas = 2ll * kit * (viso - kit);
    if (naujas > ats) {
      ats = naujas;
      kas.clear();
      kas.insert(ed.i);
    } else if (naujas == ats) {
      kas.insert(ed.i);
    }
    curr += kit;
  }
  return curr;
}
void daryk(const set<int> &nodes, const vector<vector<edge>> &edges) {
  vector<bool> visited(MX, false);
  for (auto u : nodes) {
    if (!visited[u]) {
      viso = 0;
      getsz(u, -1, edges);
      dfs(u, edges, visited);
    }
  }
  for (auto u : nodes)
    for (auto ed : edges[u]) unionSet(ed.a, ed.b);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int N;
  cin >> N;
  p = vector<int>(N + 1);
  for (int i = 0; i <= N; i++) p[i] = i;
  sz = vector<long long>(N + 1, 1);
  vector<edge> edges;
  for (int i = 0; i < N - 1; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    edges.push_back({a, b, c, i + 1});
  }
  sort(edges.begin(), edges.end(),
       [](const edge &pir, const edge &ant) { return pir.w < ant.w; });
  set<int> nodes;
  vector<vector<edge>> Cedges(MX);
  for (int i = 0; i < (int)edges.size(); i++) {
    for (auto u : nodes) Cedges[u].clear();
    nodes.clear();
    edge u = edges[i];
    u.a = findSet(u.a);
    u.b = findSet(u.b);
    nodes.insert(u.a);
    nodes.insert(u.b);
    Cedges[u.a].push_back(u);
    Cedges[u.b].push_back(u);
    while (i + 1 < (int)edges.size() and edges[i].w == edges[i + 1].w) {
      i++;
      u = edges[i];
      u.a = findSet(u.a);
      u.b = findSet(u.b);
      nodes.insert(u.a);
      nodes.insert(u.b);
      Cedges[u.a].push_back(u);
      Cedges[u.b].push_back(u);
    }
    daryk(nodes, Cedges);
  }
  printf("%lld %d\n", ats, (int)kas.size());
  for (auto u : kas) printf("%d ", u);
}
