#include "bits/stdc++.h"
#define clr(x) memset((x), 0, sizeof(x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define in(x) int (x); input((x));
#define x first
#define y second
typedef int itn;
#define next next12345
#define prev prev12345
#define left lefdsf232
#define right rig43783
#define x1 x12345
#define y1 y12345
using namespace std;
template<typename T>
T gcd(T x, T y) {
while (y > 0) {
x %= y;
swap(x, y);
}
return x;
}
template<class _T>
inline _T sqr(const _T &x) {
return x * x;
}
template<class _T>
inline string tostr(const _T &a) {
ostringstream os("");
os << a;
return os.str();
}
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const long double PI = 3.1415926535897932384626433832795L;
template<typename T>
inline void input(T &a) {
static int c;
a = 0;
while (!isdigit(c = getchar()) && c != '-') {}
char neg = 0;
if (c == '-') {
neg = 1;
c = getchar();
}
while (isdigit(c)) {
a = 10 * a + c - '0';
c = getchar();
}
if (neg) a = -a;
}
template<typename T = int>
inline T nxt() {
T res;
input(res);
return res;
}
const int N = 30000;
struct dsu {
int p[N];
int sz[N];
int cnt;
void init(int n) {
for (int i = 0; i < n; ++i) {
p[i] = i;
sz[i] = 1;
}
cnt = n;
}
inline int get(int v) {
if (p[v] != v) {
p[v] = get(p[v]);
}
return p[v];
}
inline void unite(int a, int b) {
a = get(a);
b = get(b);
if (a == b) {
return;
}
--cnt;
if (sz[a] > sz[b]) {
swap(a, b);
}
p[a] = b;
sz[b] += sz[a];
}
};
const int K = 17;
vector <dsu> x[K];
struct edge {
int from;
int to;
int len;
int id;
bool operator<(const edge & e) const {
return len < e.len;
}
};
int k;
edge e[N];
dsu empty;
dsu W;
int vertices[N + N + N + N];
int check(int l, int r) {
int p1 = (l + k - 1) / k;
int p2 = (r + 1) / k;
int X = p1 * k;
int Y = p2 * k;
p2 -= p1 + 1;
int sz = 0;
if (p2 < 0) {
for (int x = l; x <= r; ++x) {
int A = e[x].from;
int B = e[x].to;
if (A != B) {
vertices[sz++] = A;
vertices[sz++] = B;
}
}
W.cnt = empty.cnt;
for (int i = 0; i < sz; ++i) {
W.p[vertices[i]] = vertices[i];
W.sz[vertices[i]] = 1;
}
for (int x = l; x <= r; ++x) {
int A = e[x].from;
int B = e[x].to;
if (A != B) W.unite(A, B);
}
} else {
dsu & v = x[p1][p2];
for (int x = l; x < X; ++x) {
int A = v.get(e[x].from);
int B = v.get(e[x].to);
if (A != B) {
vertices[sz++] = A;
vertices[sz++] = B;
}
}
for (int x = Y; x <= r; ++x) {
int A = v.get(e[x].from);
int B = v.get(e[x].to);
if (A != B) {
vertices[sz++] = A;
vertices[sz++] = B;
}
}
W.cnt = v.cnt;
for (int i = 0; i < sz; ++i) {
W.p[vertices[i]] = vertices[i];
W.sz[vertices[i]] = 1;
}
for (int i = 0; i < sz; i += 2) {
W.unite(vertices[i], vertices[i + 1]);
}
}
return W.cnt == 1;
}
int main() {
//#define int long
#ifdef LOCAL
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#else
#define fname "onearmedbandit"
//freopen(fname".in", "r", stdin);
//freopen(fname".out", "w", stdout);
#endif
int n = nxt(), m = nxt();
for (int i = 0; i < m; ++i) {
e[i].from = nxt() - 1;
e[i].to = nxt() - 1;
e[i].len = nxt();
e[i].id = i;
}
empty.init(n);
sort(e, e + m);
k = (m + K - 1) / K;
for (int i = 0, t = 0; i < m; i += k, ++t) {
for (int j = i; j < m; ++j) {
if (j % k == 0) {
if (j == i) {
x[t].push_back(dsu());
x[t].back().init(n);
} else {
x[t].push_back(dsu());
dsu & last = x[t][x[t].size() - 2];
dsu & cur = x[t].back();
memcpy(cur.p, last.p, sizeof(int) * n);
memcpy(cur.sz, last.sz, sizeof(int) * n);
cur.cnt = last.cnt;
}
}
x[t].back().unite(e[j].from, e[j].to);
}
}
//cout << check(0, m - 1) << endl;
//return 0;
int r = 0;
int best = INT_MAX;
int L = 0, R = m - 1;
for (int i = 0; i < m; ++i) {
r = max(r, i + n - 2);
while (r < m && !check(i, r)) {
++r;
}
if (r < m) {
int v = e[r].len - e[i].len;
if (v < best) {
best = v;
L = i, R = r;
}
} else {
break;
}
}
vector <int> ans;
empty.init(n);
for (int x = L; x <= R; ++x) {
int A = empty.get(e[x].from);
int B = empty.get(e[x].to);
if (A != B) {
ans.push_back(e[x].id);
empty.unite(A, B);
}
}
// long long mem = 0;
// for (int i = 0; i < K; ++i) {
// for (const auto & X : x[i]) {
// mem += sizeof(X);
// }
// }
//
// cerr << mem << endl;
//cout << ans.size() << endl;
assert(ans.size() == n - 1);
sort(all(ans));
for (int x : ans) {
cout << x + 1 << " ";
}
cout << "\n";
#ifdef LOCAL
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}