#include <bits/stdc++.h>

using namespace std;
using int64 = long long;

constexpr int DEBUG = 0;

// Verified: AOJ-DSL1A
class UFSet {
 private:
  vector<int> ranks;
  vector<int> prevs;

 public:
  UFSet(int n) : ranks(n), prevs(n) {
    for (int i = 0; i < n; i++) prevs[i] = i;
  }

  // Returns a root of a tree which x belongs to.
  int Find(int x) {
    if (x != prevs[x]) prevs[x] = Find(prevs[x]);
    return prevs[x];
  }

  // Merges a set which x blongs to and a set which y belongs to.
  void Union(int x, int y) {
    int x_root = Find(x);
    int y_root = Find(y);
    if (ranks[x_root] > ranks[y_root]) {
      prevs[y_root] = prevs[x_root];
    } else if (ranks[x_root] < ranks[y_root]) {
      prevs[x_root] = prevs[y_root];
    } else if (prevs[x_root] != prevs[y_root]) {
      prevs[y_root] = prevs[x_root];
      ranks[x_root]++;
    }
  }
};

struct Edge {
  const int from, to, id;
  Edge(int from, int to, int id) : from(from), to(to), id(id) {}
};

template<typename T> ostream& operator<<(ostream& s, const vector<T>& v) {
  int len = v.size();
  s << "[";
  for (int i = 0; i < len; i++) {
    if (i > 0) s << ", ";
    s << v[i];
  }
  s << "]";
  return s;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n, m;
  cin >> n >> m;

  vector<pair<int64, int>> bombs;
  for (int i = 0; i < n; i++) {
    int64 x;
    int flag;
    cin >> x >> flag;
    bombs.push_back({x, flag});
  }
  sort(bombs.begin(), bombs.end());

  vector<int> flags(n + 1);
  if (bombs[0].second) flags[0] = 1;
  for (int i = 0; i < n; i++) {
    if (bombs[i].second != bombs[i + 1].second) {
      flags[i + 1] = 1;
    }
  }
  if (DEBUG) cout << "flags: " << flags << endl;

  vector<pair<int, int>> edges;
  for (int i = 0; i < m; i++) {
    int64 l, r;
    cin >> l >> r;
    int v1 = distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), make_pair(l, -1)));
    int v2 = distance(bombs.begin(), lower_bound(bombs.begin(), bombs.end(), make_pair(r, 2)));
    if (DEBUG) cout << "v1: " << v1 << " " << " v2: " << v2 << endl;
    edges.push_back(make_pair(v1, v2));
  }

  vector<int> edge_used(m);
  UFSet uf_set(n + 1);
  for (int i = 0; i < m; i++) {
    if (uf_set.Find(edges[i].first) != uf_set.Find(edges[i].second)) {
      uf_set.Union(edges[i].first, edges[i].second);
      edge_used[i] = 1;
    }
  }

  vector<int> counts(n + 1);
  for (int i = 0; i < n + 1; i++) {
    if (flags[i]) {
      counts[uf_set.Find(i)]++;
    }
  }


  for (int i = 0; i < n + 1; i++) {
    if (counts[i] % 2 == 1) {
      cout << -1 << endl;
      return 0;
    }
  }

  vector<vector<Edge>> graph(n + 1);
  for (int i = 0; i < m; i++) {
    if (!edge_used[i]) continue;
    int v1 = edges[i].first;
    int v2 = edges[i].second;
    graph[v1].push_back(Edge(v1, v2, i));
    graph[v2].push_back(Edge(v2, v1, i));
  }

  vector<int> dp(n + 1, -1);
  vector<int> outputs(m, -1);
  function<void(int, int)> dfs_fn = [&](int v, int p) {
    if (DEBUG) cout << "dfs_fn(): v = " << v << endl;
    dp[v] = 0;
    for (const auto& edge : graph[v]) {
      if (edge.to == p) continue;
      dfs_fn(edge.to, v);
      dp[v] += dp[edge.to];
      outputs[edge.id] = dp[edge.to] % 2;
    }
    if (flags[v]) dp[v]++;
  };
  for (int v = 0; v < n + 1; v++) {
    if (dp[v] >= 0) continue;
    dfs_fn(v, -1);
  }

  if (DEBUG) cout << "dp: " << dp << endl;

  int output_count = 0;
  for (int i = 0; i < m; i++) {
    if (outputs[i] == 1) output_count++;
  }
  cout << output_count << endl;
  for (int i = 0; i < m; i++) {
    if (outputs[i] == 1) cout << (i + 1) << " ";
  }
  cout << endl;
}

Measured memory_bytes: 13680