#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <class T>
ostream& operator<<(ostream& os, const vector<T>& v) {
  os << "{";
  for (int i = 0; i < (int)v.size(); i++) {
    if (i) os << ", ";
    os << v[i];
  }
  os << "}";
  return os;
}
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << " : " << arg1 << " | ";
  __f(comma + 1, args...);
}
struct tree {
  int n, block_size, num_blocks;
  vector<vector<int>> adj, val;
  vector<int> num, floorlog, par;
  tree() {}
  tree(int n) : n(n), adj(n), par(n) {}
  void add_edge(int s, int t) {
    adj[s].push_back(t);
    adj[t].push_back(s);
  }
  tree copy() {
    tree ret(n);
    ret.adj = adj;
    return ret;
  }
  vector<int> pos, tour, depth, pos_end;
  vector<vector<int>> table;
  int argmin(int i, int j) { return depth[i] < depth[j] ? i : j; }
  void rootify(int r) {
    pos.resize(n);
    pos_end.resize(n);
    function<void(int, int, int)> dfs = [&](int u, int p, int d) {
      pos[u] = pos_end[u] = depth.size();
      tour.push_back(u);
      depth.push_back(d);
      par[u] = p;
      for (int v : adj[u]) {
        if (v != p) {
          dfs(v, u, d + 1);
          pos_end[u] = (int)depth.size();
          tour.push_back(u);
          depth.push_back(d);
        }
      }
    };
    dfs(r, -1, 0);
    floorlog.resize(tour.size() + 1);
    for (int i = 0; (1 << i) <= tour.size(); i++)
      for (int j = (1 << i); j < (1 << (i + 1)) && j <= tour.size(); j++)
        floorlog[j] = i;
    int logn = floorlog[tour.size()];
    block_size = logn / 2 + 1;
    num_blocks = ((int)tour.size() - 1) / block_size + 1;
    table.resize(logn + 1, vector<int>(num_blocks));
    num.resize(num_blocks);
    val.resize(block_size + 1, vector<int>(1 << block_size));
    for (int i = 0; i < tour.size(); i += block_size) {
      int mn = i;
      int v = 0;
      int block = i / block_size;
      int j = i;
      for (; j < tour.size() && j < i + block_size; j++) {
        mn = argmin(mn, j);
        if (j != i) {
          v = 2 * v + (depth[j] == depth[j - 1] + 1);
        }
      }
      table[0][block] = mn;
      num[block] = v << (block_size - j + i);
    }
    for (int h = 1; (1 << h) <= num_blocks; ++h)
      for (int i = 0; i + (1 << h) <= num_blocks; ++i)
        table[h][i] = argmin(table[h - 1][i], table[h - 1][i + (1 << (h - 1))]);
    for (int i = 0; i < (1 << block_size); i++) {
      int prefix = 0, mn = 0, curr = 0;
      for (int j = 0; j < block_size; j++) {
        prefix += 2 * (i >> (block_size - 1 - j) & 1) - 1;
        if (mn > prefix) {
          mn = prefix;
          curr = j + 1;
        }
        val[j + 1][i >> (block_size - 1 - j)] = curr;
      }
    }
  }
  inline int same_block_lca(int block, int i, int j) {
    if (i == j) return i + block * block_size;
    int l = j - i;
    int mask = (num[block] >> (block_size - j - 1)) & ((1 << l) - 1);
    return block * block_size + i + val[l][mask];
  }
  int lca(int a, int b) {
    a = pos[a];
    b = pos[b];
    if (a > b) swap(a, b);
    int block_a = a / block_size;
    int block_b = b / block_size;
    int ind_a = a - block_a * block_size;
    int ind_b = b - block_b * block_size;
    if (block_a == block_b) return tour[same_block_lca(block_a, ind_a, ind_b)];
    int ans = argmin(same_block_lca(block_a, ind_a, block_size - 1),
                     same_block_lca(block_b, 0, ind_b));
    if (block_b > block_a + 1) {
      int h = floorlog[block_b - block_a - 1];
      int t = argmin(table[h][block_a + 1], table[h][block_b - (1 << h)]);
      ans = argmin(ans, t);
    }
    return tour[ans];
  }
  inline int dist(int i, int j) {
    return depth[pos[i]] + depth[pos[j]] - 2 * depth[pos[lca(i, j)]];
  }
  inline int getDepth(int u) { return depth[pos[u]]; }
  inline bool isAncestor(int a, int b) {
    return pos[b] >= pos[a] && pos[b] <= pos_end[a];
  }
  inline bool isOn(int c, int a, int b) {
    return isAncestor(lca(a, b), c) && (isAncestor(c, a) || isAncestor(c, b));
  }
  inline int pathsIntersect(int a, int b, int c, int d) {
    int lab = lca(a, b), lcd = lca(c, d);
    if (isOn(lab, c, d)) return lab;
    if (isOn(lcd, a, b)) return lcd;
    return -1;
  }
  vector<int> getPath(int u, int v) {
    int l = lca(u, v);
    vector<int> ret;
    while (u != l) {
      ret.push_back(u);
      u = par[u];
    }
    u = v;
    while (u != l) {
      ret.push_back(u);
      u = par[u];
    }
    ret.push_back(l);
    return ret;
  }
};
struct graph {
  vector<vector<int>> adj;
  vector<int> vis;
  vector<int> deg;
  vector<int> nodes[3];
  int n;
  graph(int n) : n(n), adj(n), vis(n), deg(n){};
  void add_edge(int a, int b) {
    adj[a].push_back(b);
    adj[b].push_back(a);
    deg[a]++;
    deg[b]++;
    deg[a] %= 3;
    deg[b] %= 3;
  }
  vector<int> getCycle() {
    vector<int> prev(n, -1);
    vector<int> depth(n, -1);
    int p = -1, c = -1;
    function<void(int, int)> dfs = [&](int s, int P) {
      vis[s] = 1;
      for (int v : adj[s]) {
        if (vis[v] == 0) {
          prev[v] = s;
          depth[v] = depth[s] + 1;
          dfs(v, s);
        } else if (vis[v] == 1 && v != P &&
                   (p == -1 || depth[c] - depth[p] > depth[s] - depth[v])) {
          p = v;
          c = s;
        }
      }
      vis[s] = 2;
    };
    for (int i = 0; i < n; i++)
      if (!vis[i]) {
        dfs(i, -1);
        if (p != -1) {
          vector<int> ret = {p};
          int curr = c;
          while (curr != p) {
            ret.push_back(curr);
            curr = prev[curr];
          }
          return ret;
        }
      }
    return {-1};
  }
  vector<int> solve() {
    clock_t st = clock();
    if (n == 1) return {-1};
    vector<int> ret;
    for (int i = 0; i < n; i++)
      if (deg[i] == 0) return {i};
    graph g2(n);
    for (int i = 0; i < n; i++)
      if (deg[i] == 2) {
        for (int j : adj[i])
          if (deg[j] == 2 && j < i) {
            g2.add_edge(i, j);
          }
      }
    vector<int> cyc = g2.getCycle();
    if (cyc[0] != -1 && ((int)(cyc).size()) != n) return cyc;
    if (((int)(cyc).size()) == n) return {-1};
    vector<int> comp(n);
    vector<vector<int>> which(n);
    int curr = 0;
    function<void(int)> dfs = [&](int s) {
      vis[s] = 1;
      comp[s] = curr;
      which[curr].push_back(s);
      for (int v : adj[s]) {
        if (!vis[v]) dfs(v);
      }
    };
    for (int i = 0; i < n; i++)
      if (!vis[i]) {
        dfs(i);
        curr++;
      }
    vector<int> prev(n, -1);
    function<int(int, int)> getPath = [&](int u, int prohibited) {
      queue<int> q;
      q.push(u);
      prev[u] = u;
      while (!q.empty()) {
        int node = q.front();
        q.pop();
        for (int node2 : adj[node])
          if (node2 != prohibited && prev[node2] == -1) {
            prev[node2] = node;
            q.push(node2);
            if (deg[node2] == 1) {
              return node2;
            }
          }
      }
      return -1;
    };
    function<void(int, int, int)> getPath2 = [&](int u, int v, int prohibited) {
      queue<int> q;
      q.push(u);
      prev[u] = u;
      while (!q.empty()) {
        int node = q.front();
        q.pop();
        for (int node2 : adj[node])
          if (node2 != prohibited && prev[node2] == -1) {
            prev[node2] = node;
            q.push(node2);
            if (node2 == v) return;
          }
      }
      return;
    };
    vector<vector<vector<int>>> dp(n,
                                   vector<vector<int>>(3, vector<int>(3, 0)));
    vector<int> isNeighbour(n, 0);
    for (int i = 0; i < curr; i++) {
      int node = -1;
      for (int j : which[i]) {
        if (deg[j] == 1) {
          if (node != -1) {
            int en = getPath(j, -1);
            ret.push_back(j);
            while (en != j) {
              ret.push_back(en);
              en = prev[en];
            }
            if (((int)(ret).size()) == n) return {-1};
            return ret;
          }
          node = j;
        }
      }
      if (node != -1) {
        vector<int> d1nodes;
        function<void(int, int)> dfs2 = [&](int s, int p) {
          vis[s] = 1;
          if (isNeighbour[s]) d1nodes.push_back(s);
          for (int v : adj[s])
            if (v != p && v != node) dfs2(v, s);
        };
        for (int j : adj[node]) isNeighbour[j] = 1;
        vector<vector<int>> leaves;
        vis.assign(n, 0);
        for (int j : which[i])
          if (j != node && !vis[j]) {
            d1nodes.clear();
            dfs2(j, -1);
            leaves.push_back(d1nodes);
          }
        if (((int)(leaves).size()) >= 2) {
          assert(((int)(leaves[0]).size()) >= 2 &&
                 ((int)(leaves[1]).size()) >= 2);
          ret.clear();
          ret.push_back(node);
          function<void(int, int)> gp = [&](int P, int Q) {
            ret.push_back(P);
            while (Q != P) {
              ret.push_back(Q);
              Q = prev[Q];
            }
          };
          prev.assign(n, -1);
          getPath2(leaves[0][0], leaves[0][1], node);
          gp(leaves[0][0], leaves[0][1]);
          getPath2(leaves[1][0], leaves[1][1], node);
          gp(leaves[1][0], leaves[1][1]);
          return ret;
        }
        assert(((int)(leaves[0]).size()) >= 4);
        int u = leaves[0][0], v = leaves[0][1], x = leaves[0][2],
            y = leaves[0][3];
        tree T(n);
        int root = -1;
        for (int j : which[i])
          if (j != node) {
            root = j;
            for (int k : adj[j])
              if (k != node && k < j) T.add_edge(j, k);
          }
        T.rootify(root);
        int z = T.pathsIntersect(u, v, x, y);
        if (z == -1) {
          ret = T.getPath(u, v);
          vector<int> ret1 = T.getPath(x, y);
          for (int w : ret1) ret.push_back(w);
          return ret;
        } else {
          int deepest = -1, maxDepth = -1;
          vector<int> num(n, 0);
          vector<int> st(n, 0), en(n, 0);
          vector<int> depth(n, 0);
          int timer = 0;
          function<void(int, int, int)> go = [&](int s, int p, int d) {
            num[s] = isNeighbour[s];
            st[s] = ++timer;
            depth[s] = d;
            for (int v : adj[s])
              if (v != p && v != node) {
                go(v, s, d + 1);
                num[s] += num[v];
              }
            if (num[s] >= 2 && d > maxDepth) {
              maxDepth = d;
              deepest = s;
            }
            en[s] = timer;
          };
          if (deepest == z) return {-1};
          vector<int> L[2];
          function<void(int, int)> findLeaves = [&](int s, int pos) {
            if (isNeighbour[s]) L[pos].push_back(s);
            for (int v : adj[s])
              if (v != node && v != deepest && depth[v] > depth[s]) {
                findLeaves(v, pos);
              }
          };
          findLeaves(z, 0);
          findLeaves(deepest, 1);
          if (((int)(L[0]).size()) < 2 || ((int)(L[1]).size()) < 2) return {-1};
          int u = L[0][0], v = L[0][1], x = L[1][0], y = L[1][1];
          ret = T.getPath(u, v);
          vector<int> ret1 = T.getPath(x, y);
          for (int w : ret1) ret.push_back(w);
          return ret;
        }
      }
    }
    return {-1};
  }
};
int main() {
  int t;
  scanf("%d", &(t));
  while (t--) {
    int n, m;
    scanf("%d", &(n));
    scanf("%d", &(m));
    graph g(n);
    for (int i = 1; i <= m; i++) {
      int u, v;
      scanf("%d", &(u));
      scanf("%d", &(v));
      u--;
      v--;
      g.add_edge(u, v);
    }
    vector<int> choose = g.solve();
    if (choose[0] == -1) {
      printf("No\n");
      continue;
    }
    vector<int> rem(n, 1);
    for (int v : choose) rem[v] = 0;
    vector<int> ans;
    for (int i = 0; i < n; i++) {
      if (rem[i]) ans.push_back(i);
    }
    if (((int)(ans).size()) == 0 || ((int)(ans).size()) == n) {
      printf("No\n");
      continue;
    }
    printf("Yes\n");
    printf("%d\n", ((int)(ans).size()));
    for (auto it : ans) printf("%d ", it + 1);
    printf("\n");
  }
}
