/* Beautiful Codes are MUCH better than 'Shorter' ones ! user : triveni date : 22/04/2018 time : 04:34:32 */ #include using namespace std; #define pii std::pair #define vi std::vector #define sz(v) (int)(v.size()) #define mp(a,b) make_pair(a,b) #define pb(a) push_back(a) #define each(it,s) for(auto it = s.begin(); it != s.end(); ++it) #define rep(i, n) for(int i = 0; i < (n); ++i) #define rep1(i, n) for(int i = 1; i <= (n); ++i) #define all(v) v.begin(), v.end() #define scan(n) scanf("%d", &n) #define scan2(n, m) scanf("%d%d", &n, &m) #define pin(n) printf("%d\n",n) #define pis(n) printf("%d ",n) #define pll(n) printf("%lld\n", n) #define X first #define Y second typedef long long ll; const ll mod = 1000000007; inline int pow_(ll a, int n, int p=mod){ int r=1;while(n){if(n&1)r=r*a%p;n>>=1;a=a*a%p;}return r;} inline int inv_(int a) {return pow_(a, mod-2, mod);} inline int add(int a, int b){a+=b;if(a>=mod)a-=mod;return a;} inline void adds(int& a, int b){a+=b;if(a>=mod)a-=mod;} inline int mul(int a, int b){return a*1ll*b%mod;} inline void muls(int& a, int b){a=a*1ll*b%mod;} inline int sub(int a, int b){a-=b;if(a<0)a+=mod;return a;} vector E; int n, m; int col[10010]; vector graph[100]; int vis[10010]; const int RED = 0; const int GREEN = 1; inline int getV(int e, int u) { if(e < 0) return e; return E[e].X + E[e].Y - u; } void initColor(int u, int curCol) { vis[u] = 1; for (int e : graph[u]) if(col[e] == -1) { int c = getV(e, u); if(vis[c]) continue; col[e] = curCol; initColor(c, curCol); } } int lev[2][100]; int par[2][100]; bool conn[10010]; void root(int u, int curCol, int p = -1) { for (int e : graph[u]) if(col[e] == curCol && p != e) { int c = getV(e, u); lev[curCol][c] = lev[curCol][u] + 1; par[curCol][c] = e; root(c, curCol, e); } } int lca(int u, int v, int curCol) { if(lev[curCol][u] > lev[curCol][v]) return lca(v, u, curCol); while(lev[curCol][v] > lev[curCol][u]) v = getV(par[curCol][v], v); while(u != v) { v = getV(par[curCol][v], v); u = getV(par[curCol][u], u); } return u; } void rootTrees() { rep(i, n) { lev[RED][i] = lev[GREEN][i] = 0; par[RED][i] = par[GREEN][i] = -1; } root(0, RED); rep(i, n) if(lev[GREEN][i] == 0) root(i, GREEN); rep(i, m) { conn[i] = col[i]==RED && lca(E[i].X, E[i].Y, GREEN) == -1; } } vector edgeG[10010]; void addEdge(int e, int curCol) { int u = E[e].X, v = E[e].Y; int r = lca(u, v, curCol ^ 1); if(r == -1) return ; for (int x : {u, v}){ while(x != r) { int p = par[curCol^1][x]; edgeG[e].pb(p); x = getV(p, x); } } } int dis[10010]; int dad[10010]; int bfs(int u) { // note that this u is edge rep(i, m) dad[i] = -1, dis[i] = mod; dis[u] = 0; queue Q; Q.push(u); int connE = -1; while(!Q.empty()) { u = Q.front(); Q.pop(); if(conn[u] && connE == -1) connE = u; for (int c : edgeG[u]) if(dis[c] > dis[u] + 1) { Q.push(c); dis[c] = dis[u] + 1; dad[c] = u; } } return connE; } void addRedEdge(int u, int p, vi & deg, vi & edgeList) { for (int e : graph[u]) if(col[e] == RED && p != e) { addRedEdge(getV(e, u), e, deg, edgeList); } if(deg[u] & 1) { assert(p != -1); deg[u] += 1; deg[getV(p, u)] += 1; edgeList.pb(p); } } // print euler circuit list path; void epath(int u, list::iterator it) { while(!graph[u].empty()) { int e = graph[u].back(); graph[u].pop_back(); if(vis[e]) continue; vis[e] = 1; it = path.insert(it, e); auto newIt = it; newIt++; epath(getV(e, u), newIt); } } void solve() { scan2(n, m); E.resize(m); rep(i, n) graph[i].clear(); rep(i, m) { int u, v; scan2(u, v); --u, --v; E[i] = mp(u, v); col[i] = -1; graph[u].pb(i); graph[v].pb(i); } rep(i, n) vis[i] = 0; initColor(0, RED); rep(i, n) vis[i] = 0; rep(i, n) if(!vis[i]) initColor(i, GREEN); for (int e = 0; e < m; ++e) if(col[e] == -1) { rootTrees(); // build edge graph rep(i, m) edgeG[i].clear(); rep(i, m) if(col[i] != -1) addEdge(i, col[i]); addEdge(e, RED); addEdge(e, GREEN); int x = bfs(e); if(x == -1) continue; while(dad[x] != e) { col[x] ^= 1; x = dad[x]; } col[x] ^= 1; col[e] = col[x]^1; } rootTrees(); // now run the actual algorithm vector edgeList; vector deg(n); rep(i, m) if(col[i] == GREEN) { edgeList.pb(i); deg[E[i].X] += 1; deg[E[i].Y] += 1; } addRedEdge(0, -1, deg, edgeList); // now find euler tour from the edges in edgeList rep(i, n) graph[i].clear(); for (int i : edgeList) graph[E[i].X].pb(i), graph[E[i].Y].pb(i); rep(i, m) vis[i] = 0; path.clear(); epath(0, path.begin()); int ans = sz(path); pis(ans); for (int e : path) pis(e+1); putchar(10); } int main() { int T; scan(T); while(T--) solve(); return 0; }