#include <cstdio>
#include <cassert>
#include <algorithm>
#include <vector>
#include <list>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
#define _submit
#ifdef _submit
#define InFile "critice.in"
#define OtFile "critice.out"
#else
#define InFile "fis.in"
#define OtFile "fis.out"
#endif
class edge {
private:
int toNod, capacity, *flow;
edge(int N, int p, int* f) {
toNod = N;
capacity = p;
flow = f;
}
friend class graph;
};
class edge2 {
private:
int n1, n2, *flow, cap;
edge2(int N1, int N2, int* FLOW, int CAP) {
n1 = N1; n2 = N2; flow = FLOW; cap = CAP;
}
friend class graph;
};
class graph {
private:
vector< list<edge> > adiac;
vector< edge2 > edgeTracker;
public:
graph(int N, int M) {
adiac.resize(N + 1);
edgeTracker.reserve(M + 2);
}
void addEdge(int n1, int n2, int cap) {
int* f = new int(0);
adiac[n1].push_back(edge(n2, cap, f));
adiac[n2].push_back(edge(n1, cap, f));
adiac[n1].push_back(edge(-n2, cap, f));
adiac[n2].push_back(edge(-n1, cap, f));
edgeTracker.push_back(edge2(n1, n2, f, cap));
}
int size() { return adiac.size() - 1; }
int sendFlows(int nod, int endNod, vector<int> &parent, vector<int*> &flowArcToParent, vector<int> &capArcToParent, vector<char> &isForwardArc, queue<int>& Q) {
int s = 0;
memset(&parent[0], 0xFF, parent.size()*sizeof(parent[0]));
while (!Q.empty())
Q.pop();
Q.push(nod);
parent[nod] = 0;
while (!Q.empty()) {
int t = Q.front();
Q.pop();
for (auto i = adiac[t].begin(); i != adiac[t].end(); ++i) {
if (t == nod && i->toNod < 0)
continue;
int curnod = i->toNod > 0 ? i->toNod : -(i->toNod);
if (curnod == endNod) {
if (i->toNod < 0)
continue;
int MF = i->capacity - *i->flow;
if (!MF)
continue;
int aux = t;
while (parent[aux]) {
int availableFlow = isForwardArc[aux] ? capArcToParent[aux] - *flowArcToParent[aux] : *flowArcToParent[aux];
if (!availableFlow)
break;
if (availableFlow < MF)
MF = availableFlow;
aux = parent[aux];
}
if (!parent[aux]) {
if (i->toNod > 0)
*i->flow += MF;
else
*i->flow -= MF;
aux = t;
while (parent[aux]) {
if (isForwardArc[aux])
*flowArcToParent[aux] += MF;
else
*flowArcToParent[aux] -= MF;
aux = parent[aux];
}
s += MF;
return s;
}
}
else if (parent[curnod] == -1) {
int availableFlow = i->toNod > 0 ? i->capacity - *i->flow : *i->flow;
if (availableFlow) {
Q.push(curnod);
parent[curnod] = t;
flowArcToParent[curnod] = i->flow;
capArcToParent[curnod] = i->capacity;
if (i->toNod > 0)
isForwardArc[curnod] = 1;
else
isForwardArc[curnod] = 0;
}
}
}
}
return s;
}
int EdmondsKarp(int source, int sink) {
int s = 0;
vector<int> parent(size() + 1), caps(size() + 1);
vector<int*> flows(size() + 1);
vector<char> isForward(size() + 1);
queue<int> Q;
while (true) {
int flowSent = sendFlows(source, sink, parent, flows, caps, isForward, Q);
if (!flowSent)
break;
s += flowSent;
//fprintf(stderr, "%d\n", s);
}
return s;
}
void unsaturatedDFS(int nod, vector<char> &visited) {
visited[nod] = 1;
for (auto i = adiac[nod].begin(); i != adiac[nod].end(); ++i)
if (i->toNod > 0 && !visited[i->toNod] && *i->flow != i->capacity)
unsaturatedDFS(i->toNod, visited);
}
void criticalEdges() {
int N = size();
EdmondsKarp(1, N);
vector<char> visitedFromSource(N + 1, 0);
unsaturatedDFS(1, visitedFromSource);
vector<char> visitedFromSink(N + 1, 0);
unsaturatedDFS(N, visitedFromSink);
list<int> sol;
for (auto i = edgeTracker.begin(); i != edgeTracker.end(); ++i)
if (*i->flow == i->cap && ((visitedFromSource[i->n1] && visitedFromSink[i->n2]) || (visitedFromSource[i->n2] && visitedFromSink[i->n1])))
sol.push_back(distance(edgeTracker.begin(), i) + 1);
printf("%d\n", sol.size());
for (auto i = sol.begin(); i != sol.end(); ++i)
printf("%d\n", *i);
}
};
int main() {
assert(freopen(InFile, "r", stdin));
assert(freopen(OtFile, "w", stdout));
int N, M;
scanf("%d%d", &N, &M);
graph* G = new graph(N, M);
for (int i = 0; i < M; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
G->addEdge(a, b, c);
}
G->criticalEdges();
return 0;
}