#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
ifstream fin("critice.in");
ofstream fout("critice.out");
struct flow_edge {
int u, v, cap;
bool is_fake;
flow_edge(int _u, int _v, int _cap, bool _is_fake) : u(_u), v(_v), cap(_cap), is_fake(_is_fake) {}
};
struct Dinic {
int n, m = 0, s, t;
vector<flow_edge> edges;
vector<vector<int>> adj;
vector<int> level, ptr;
queue<int> q;
vector<bool> viz, from_one, from_n;
set<pair<int, int>> saturated_edges;
Dinic(int N, int source, int sink) : n(N), s(source), t(sink) {
adj.resize(n + 1);
level.resize(n + 1);
ptr.resize(n + 1);
viz.resize(n + 1);
from_one.resize(n + 1);
from_n.resize(n + 1);
}
void add_edge(int u, int v, int cap) {
edges.emplace_back(u, v, cap, false);
adj[u].emplace_back(m++);
edges.emplace_back(v, u, 0, true);
adj[v].emplace_back(m++);
}
bool bfs() {
while (!q.empty()) {
int curr = q.front();
q.pop();
for (int id : adj[curr])
if (level[edges[id].v] == -1 && edges[id].cap) {
level[edges[id].v] = level[curr] + 1;
q.emplace(edges[id].v);
}
}
return level[t] != -1;
}
int dfs(int u, int curr_flow) {
if (curr_flow == 0)
return 0;
if (u == t)
return curr_flow;
for (int& p = ptr[u]; p < static_cast<int>(adj[u].size()); ++p) {
int id = adj[u][p];
int v = edges[id].v;
if (level[u] + 1 != level[v] || edges[id].cap <= 0)
continue;
int new_flow = dfs(v, min(curr_flow, edges[id].cap));
if (new_flow == 0)
continue;
edges[id].cap -= new_flow;
edges[id ^ 1].cap += new_flow;
return new_flow;
}
return 0;
}
void max_flow() {
while (true) {
fill(level.begin(), level.end(), -1);
level[s] = 0;
q.emplace(s);
if (!bfs())
break;
fill(ptr.begin(), ptr.end(), 0);
while (dfs(s, INF));
}
}
void reach(int u, bool type) {
if (viz[u]) {
return;
}
viz[u] = true;
if (type) {
from_one[u] = true;
} else {
from_n[u] = true;
}
for (const int &id : adj[u]) {
if (edges[id].cap > 0) {
reach(edges[id].v, type);
}
}
}
void find_saturated_edges() {
for (const auto &it : edges) {
if (!it.is_fake && it.cap == 0) {
saturated_edges.emplace(it.u, it.v);
}
}
}
};
int main() {
int n, m;
fin >> n >> m;
Dinic g(n, 1, n);
vector<pair<int,int>> edges(m);
for (int i = 0; i < m; ++i) {
int u, v, w;
fin >> u >> v >> w;
g.add_edge(u, v, w);
g.add_edge(v, u, w);
edges[i] = make_pair(u, v);
}
g.max_flow();
g.reach(1, true);
g.viz = vector<bool>(n + 1, false);
g.reach(n, false);
g.find_saturated_edges();
vector<int> sol;
for (size_t i = 0; i < edges.size(); ++i) {
int u, v;
tie(u, v) = edges[i];
if ((g.from_one[u] && g.from_n[v]) || (g.from_one[v] && g.from_n[u])) {
if (g.saturated_edges.count(edges[i])) {
sol.emplace_back(i + 1);
} else {
swap(edges[i].first, edges[i].second);
if (g.saturated_edges.count(edges[i])) {
sol.emplace_back(i + 1);
}
}
}
}
fout << sol.size() << '\n';
for (const auto &it : sol)
fout << it << '\n';
fin.close();
fout.close();
return 0;
}