#include <bits/stdc++.h>
using namespace std;
inline bool _R(int &x) { return scanf("%d", &x) == 1; }
inline bool _R(long long &x) { return scanf("%lld", &x) == 1; }
inline bool _R(double &x) { return scanf("%lf", &x) == 1; }
inline bool _R(char &x) { return scanf(" %c", &x) == 1; }
inline bool _R(char *x) { return scanf("%s", x) == 1; }
template <typename T, typename U>
inline bool _R(pair<T, U> &x) {
  return _R(x.first) && _R(x.second);
}
inline bool Read() { return 1; }
template <typename T, typename... U>
inline bool Read(T &head, U &...tail) {
  return _R(head) && Read(tail...);
}
inline void _W(const int &x) { printf("%d", x); }
inline void _W(const long long &x) { printf("%lld", x); }
inline void _W(const double &x) { printf("%.10f", x); }
inline void _W(const char &x) { putchar(x); }
inline void _W(const char *x) { printf("%s", x); }
template <typename T, typename U>
inline void _W(const pair<T, U> &x) {
  _W(x.first);
  putchar(' ');
  _W(x.second);
}
template <typename T>
inline void _W(const vector<T> &x) {
  for (auto i = x.begin(); i != x.end(); _W(*i++)) {
    if (i != x.begin()) {
      putchar(' ');
    }
  }
}
inline void Write() {}
template <typename T, typename... U>
inline void Write(const T &head, const U &...tail) {
  _W(head);
  putchar(sizeof...(tail) ? ' ' : '\n');
  Write(tail...);
}
const int Move[][2] = {{0, 0}, {1, 0},  {0, 1},  {0, -1}, {-1, 0},
                       {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
void solve();
int32_t main() {
  solve();
  2333;
}
const int MOD = 1e9 + 7;
inline long long sqr(long long a) { return a * a; }
inline long long add(long long a, long long b) {
  a += b;
  return (a >= MOD) ? (a - MOD) : a;
}
inline long long sub(long long a, long long b) {
  a -= b;
  return (a < 0) ? (a + MOD) : a;
}
inline long long mul(long long a, long long b) {
  a *= b;
  if (a >= MOD) a = a - a / MOD * MOD;
  return a;
}
template <typename T>
inline bool chkmin(T &a, T b) {
  return (a > b) ? (a = b, true) : false;
}
template <typename T>
inline bool chkmax(T &a, T b) {
  return (a < b) ? (a = b, true) : false;
}
long long Pow(long long a, long long t) {
  long long b = 1;
  for (; t > 0; t >>= 1, a *= a)
    if (t & 1) b *= a;
  return b;
}
long long qpow(long long a, long long t) {
  long long b = 1;
  for (; t > 0; t >>= 1, a = mul(a, a))
    if (t & 1) b = mul(b, a);
  return b;
}
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
struct node {
  int u;
  long long w;
  node(int a = 0, long long b = 0) : u(a), w(b) {}
  bool operator<(const node &b) const { return w > b.w; }
};
struct edge {
  int v, next;
  long long w;
  edge(int a = 0, int b = 0, long long c = 0) : v(a), next(b), w(c) {}
} G[maxn << 1];
int tot, head[maxn], pre[maxn];
long long dis[maxn];
bool vis[maxn];
vector<int> ans;
int n, k;
map<pair<int, int>, int> Map;
void init() {
  tot = 0;
  Map.clear(), ans.clear();
  memset(vis, 0, sizeof vis);
  memset(pre, -1, sizeof pre);
  memset(head, -1, sizeof head);
  memset(dis, 0x3f, sizeof dis);
}
void addedge(int u, int v, int w, int id) {
  if (u > v) swap(u, v);
  Map[{u, v}] = id;
  G[tot] = edge(v, head[u], w);
  head[u] = tot++;
  G[tot] = edge(u, head[v], w);
  head[v] = tot++;
}
void addans(int u, int v) {
  if (u > v) swap(u, v);
  ans.push_back(Map[{u, v}]);
}
void Dijkstra() {
  priority_queue<node> Q;
  Q.emplace(1, 0), dis[1] = 0;
  while (!Q.empty()) {
    int u = Q.top().u;
    Q.pop();
    if (vis[u])
      continue;
    else
      vis[u] = 1;
    if (pre[u] != -1) addans(pre[u], u);
    if ((int)ans.size() == k) return;
    for (int i = head[u]; i != -1; i = G[i].next) {
      edge &e = G[i];
      if (!vis[e.v] && chkmin(dis[e.v], dis[u] + e.w)) {
        pre[e.v] = u;
        Q.emplace(e.v, dis[e.v]);
      }
    }
  }
}
void solve() {
  int m;
  while (Read(n, m, k)) {
    init();
    for (int i = 1; i <= m; i++) {
      int u, v, w;
      Read(u, v, w);
      addedge(u, v, w, i);
    }
    Dijkstra();
    Write((int)ans.size());
    Write(ans);
  }
}
