Problem: I'm the Map, I'm the Map! I'm the MAP!!!

Map

In anticipation of new adventures Boots wanted to do a good deed. After discussion with the Map and Backpack, they decided to gift Dora a connected graph. After a long search, Boots chose t graph's variants, which Dora might like. However fox Swiper wants to spoil his plan.

The Swiper knows, that Dora now is only able to count up to 3, so he has came up with a following idea. He wants to steal some non-empty set of vertices, so that the Dora won't notice the loss. He has decided to steal some non-empty set of vertices, so that after deletion of the stolen vertices and edges adjacent to them, every remaining vertex wouldn't change it's degree modulo 3. The degree of a vertex is the number of edges it is adjacent to. It would've been suspicious to steal all the vertices, so Swiper needs another plan.

Boots are sure, that the crime can not be allowed. However they are afraid, that they won't be able to handle this alone. So Boots decided to ask for your help. Please determine for every graph's variant whether the Swiper can perform the theft or not.

Input

The first line contains a single integer t (1 ≤ t ≤ 100 000) — the number of graph variants.

The first line of each variant contains integers n, m (1 ≤ n ≤ 500 000, 0 ≤ m ≤ 500 000), the number of vertexes and edges in the graph.

Then m lines follow, each containing integers a_i, b_i (1 ≤ a_i, b_i ≤ n), the indices of the vertices connected with a corresponding edge.

It's guaranteed, that the graph is connected and doesn't contain multiple edges or self-loops.

It's guaranteed, that the sum of n over all variants is at most 500 000 and that the sum of m over all variants is at most 500 000.

Descriptions of graph's variants are separated with an empty line.

Output

For each variant:

  * In case the answer exists, print "Yes" and then the answer itself.

The first line should contain an integer c (1 < c < n), the number of vertices the Crook can steal, without Dora noticing the loss. On the next line print c distinct integers, the indices of the graph's vertices in arbitrary order.

  * Otherwise print "No". 



In case there are several correct ways to steal the vertices, print any of them.

Please note, that it's not required to maximize the number of stolen vertices.

Example

Input


3
3 3
1 2
2 3
3 1

6 6
1 2
1 3
2 3
2 5
2 6
2 4

8 12
1 2
1 3
2 3
1 4
4 5
5 1
3 6
3 7
3 8
6 1
7 1
8 1


Output


No
Yes
3
4 5 6
Yes
3
6 7 8

Note

The picture below shows the third variant from the example test. The set of the vertices the Crook can steal is denoted with bold. 

<image>

Solution (in CPP):

Solution:
#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");
  }
}