#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; //////////// graph typedef long long int Weight; struct Edge { int src, dest; Weight weight; int id; Edge() {} Edge(int src, int dest, Weight weight, int id) : src(src), dest(dest), weight(weight), id(id) { } friend bool operator<(const Edge& a, const Edge& b) { return (a.weight < b.weight); } friend bool operator>(const Edge& a, const Edge& b) { return (a.weight > b.weight); } }; typedef vector Edges; typedef vector Graph; const Weight WEIGHT_INFTY = numeric_limits::max()/4; inline void insert_edge(Graph& g, int a, int b, Weight w, int id) { g[a].push_back(Edge(a, b, w, id)); } enum Const { UNSEEN = -1 , TERMINAL = -2 }; Weight dijkstra(const Graph& g, int start, int goal, vector< pair >& trace) { const int n = g.size(); trace.assign(n, make_pair(UNSEEN, WEIGHT_INFTY)); priority_queue, greater > q; q.push(Edge(TERMINAL, start, 0, -1)); while(!q.empty()) { Edge edge = q.top(); q.pop(); if (trace[edge.dest].first != UNSEEN) continue; trace[edge.dest] = make_pair(edge.src, edge.weight); // if (edge.dest == goal) // return edge.weight; const Edges& edges = g[edge.dest]; for(int i = 0; i < (int)edges.size(); i++) { if (trace[edges[i].dest].first == UNSEEN) { q.push(Edge(edge.dest, edges[i].dest, edge.weight + edges[i].weight, -1)); } } } return WEIGHT_INFTY; } int main() { int nCities, nRoads; Weight alpha; ifstream fin("almost.in"); bool first = true; while(fin >> nCities >> nRoads >> alpha) { if(!nCities && !nRoads && !alpha) break; Graph g(nCities), g_reverse(nCities); for(int i = 0; i < nRoads; i++) { int src, dest; Weight weight; fin >> src >> dest >> weight; src--; dest--; insert_edge(g, src, dest, weight, i); insert_edge(g_reverse, dest, src, weight, i); //assert(weight >= 0); } vector< pair > trace, trace_reverse; dijkstra(g, 0, nCities-1, trace); dijkstra(g_reverse, nCities-1, 0, trace_reverse); set answer; if (trace[nCities-1].first != UNSEEN) { Weight mindist = trace[nCities-1].second; //assert(mindist != WEIGHT_INFTY); #if 0 cout << "mindist = " << mindist << endl; for(int i = 0; i < (int)g.size(); i++) { cout << i << ": " << trace[i].first << ", " << trace[i].second << endl; } for(int i = 0; i < (int)g.size(); i++) { cout << i << ": " << trace_reverse[i].first << ", " << trace_reverse[i].second << endl; } #endif for(int i = 0; i < (int)g.size(); i++) { Edges& edges = g[i]; for(int j = 0; j < (int)edges.size(); j++) { Edge& e = edges[j]; if(trace[e.src].first != UNSEEN && trace_reverse[e.dest].first != UNSEEN) { Weight dist = trace[e.src].second + e.weight + trace_reverse[e.dest].second; if(dist <= mindist + alpha) answer.insert(e.id); } } } } if(first) first = false; else cout << endl; cout << answer.size() << endl; for(set::const_iterator it = answer.begin(); it != answer.end(); it++) cout << (*it)+1 << endl; } return 0; }