#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; static const double EPS = 1e-8; static const double PI = 4.0 * atan(1.0); static const double PI2 = 8.0 * atan(1.0); typedef long long ll; typedef unsigned long long ull; #define ALL(c) (c).begin(), (c).end() #define CLEAR(v) memset(v,0,sizeof(v)) #define MP(a,b) make_pair((a),(b)) #define REP(i,n) for(int i=0;i<(int)n;++i) #define ABS(a) ((a)>0?(a):-(a)) template T MIN(const T& a, const T& b) { return a < b ? a : b; } template T MAX(const T& a, const T& b) { return a > b ? a : b; } template void MIN_UPDATE(T& a, const T& b) { if (a > b) a = b; } template void MAX_UPDATE(T& a, const T& b) { if (a < b) a = b; } typedef int Weight; struct Edge { int src, dst; Weight weight; Edge(int src, int dst, Weight weight) : src(src), dst(dst), weight(weight) { } }; bool operator < (const Edge &e, const Edge &f) { return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!! e.src != f.src ? e.src < f.src : e.dst < f.dst; } typedef vector Edges; typedef vector Graph; typedef vector Array; typedef vector Matrix; static const int INF = INT_MAX / 3; #define RESIDUE(s,t) (capacity[s][t]-flow[s][t]) Weight augment(const Graph &g, const Matrix &capacity, Matrix &flow, const vector &level, vector &finished, int u, int t, Weight cur) { if (u == t || cur == 0) return cur; if (finished[u]) return 0; finished[u] = true; for (Edges::const_iterator e = g[u].begin(), eEnd = g[u].end(); e != eEnd; ++e) if (level[e->dst] > level[u]) { Weight f = augment(g, capacity, flow, level, finished, e->dst, t, min(cur, RESIDUE(u, e->dst))); if (f > 0) { flow[u][e->dst] += f; flow[e->dst][u] -= f; finished[u] = false; return f; } } return 0; } Weight maximumFlow(const Graph &g, int s, int t, Matrix& flow, Matrix& capacity) { int n = g.size(); flow.resize(n, Array(n)); capacity.resize(n, Array(n)); // adj. matrix REP(u,n) for (Edges::const_iterator e = g[u].begin(), eEnd = g[u].end(); e != eEnd; ++e) capacity[e->src][e->dst] += e->weight; Weight total = 0; for (bool cont = true; cont; ) { cont = false; vector level(n, -1); level[s] = 0; // make layered network queue Q; Q.push(s); for (int d = n; !Q.empty() && level[Q.front()] < d; ) { int u = Q.front(); Q.pop(); if (u == t) d = level[u]; for (Edges::const_iterator e = g[u].begin(), eEnd = g[u].end(); e != eEnd; ++e) if (RESIDUE(u,e->dst) > 0 && level[e->dst] == -1) Q.push(e->dst), level[e->dst] = level[u] + 1; } vector finished(n); // make blocking flows for (Weight f = 1; f > 0; ) { f = augment(g, capacity, flow, level, finished, s, t, INF); if (f == 0) break; total += f; cont = true; } } return total; } int main() { for (int N, M; cin >> N >> M && (N || M);) { Graph g(N + 1); Edges edges; REP(m, M) { int s, t; cin >> s >> t; const Edge edge(s, t, 1); g[s].push_back(edge); g[t].push_back(Edge(t, s, 1)); edges.push_back(edge); } int s, t; cin >> s >> t; Matrix flow, capacity; const Weight w = maximumFlow(g, s, t, flow, capacity); cout << w << endl; vector reversed; REP(m, M) { const Edge& edge = edges[m]; if (flow[edge.dst][edge.src] > 0) { reversed.push_back(m + 1); } } cout << reversed.size() << endl; REP(i, reversed.size()) { cout << reversed[i] << endl; } } }