#include <bits/stdc++.h>
using namespace std;
ifstream fin("critice.in");
ofstream fout("critice.out");
struct Edge {
int to, rev, cap;
};
int n, m;
vector<vector<Edge>> G;
vector<int> level, ptr;
vector<int> A, B, C;
vector<int> fromStart, fromEnd;
vector<int> sol;
void addEdge(int x, int y, int cap) {
Edge a = {y, (int)G[y].size(), cap};
Edge b = {x, (int)G[x].size(), cap};
G[x].push_back(a);
G[y].push_back(b);
}
bool bfs() {
queue<int> Q;
level.assign(n + 1, -1);
Q.push(1);
level[1] = 0;
while (!Q.empty()) {
int node = Q.front();
Q.pop();
for (auto edge : G[node]) {
if (edge.cap > 0 && level[edge.to] == -1) {
level[edge.to] = level[node] + 1;
Q.push(edge.to);
}
}
}
return level[n] != -1;
}
int dfs(int node, int flow) {
if (node == n || flow == 0)
return flow;
for (int &i = ptr[node]; i < (int)G[node].size(); ++i) {
Edge &edge = G[node][i];
if (edge.cap > 0 && level[edge.to] == level[node] + 1) {
int pushed = dfs(edge.to, min(flow, edge.cap));
if (pushed) {
edge.cap -= pushed;
G[edge.to][edge.rev].cap += pushed;
return pushed;
}
}
}
return 0;
}
void dinic() {
while (bfs()) {
ptr.assign(n + 1, 0);
while (dfs(1, 2e9));
}
}
void dfsResidual(int node, vector<int> &visited) {
visited[node] = 1;
for (auto edge : G[node]) {
if (edge.cap > 0 && !visited[edge.to])
dfsResidual(edge.to, visited);
}
}
int main() {
fin >> n >> m;
G.resize(n + 1);
A.resize(m + 1);
B.resize(m + 1);
C.resize(m + 1);
for (int i = 1; i <= m; ++i) {
fin >> A[i] >> B[i] >> C[i];
addEdge(A[i], B[i], C[i]);
}
dinic();
fromStart.assign(n + 1, 0);
fromEnd.assign(n + 1, 0);
dfsResidual(1, fromStart);
dfsResidual(n, fromEnd);
for (int i = 1; i <= m; ++i) {
if (fromStart[A[i]] && fromEnd[B[i]])
sol.push_back(i);
if (fromStart[B[i]] && fromEnd[A[i]])
sol.push_back(i);
}
sort(sol.begin(), sol.end());
fout << sol.size() << "\n";
for (int id : sol)
fout << id << "\n";
return 0;
}