#include"bits/stdc++.h"
using namespace std;
#define REP(k,m,n) for(int (k)=(m);(k)<(n);(k)++)
#define rep(i,n) REP((i),0,(n))
using ll = long long;
using pll = pair<ll, ll>;
using ar3 = array<ll, 3>;
using SparseGraph = map<ll, vector<pll>>; // from => (to, idx)[]
constexpr ll INF = 1ll << 60;

class UnionFind {
public:
    vector<int>rank, parent;
    //初期化
    UnionFind(int size) {
        rank.resize(size, 0);
        parent.resize(size, 0);
        rep(i, size)parent[i] = i;
    }
    //木の根を求める
    int find(int x) {
        if (parent[x] == x)return x;
        else return parent[x] = find(parent[x]);
    }
    //xとyの属する集合を併合
    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y)return;
        if (rank[x] < rank[y])
            parent[x] = y;
        else {
            parent[y] = x;
            if (rank[x] == rank[y])rank[x]++;
        }
    }
    //xとyが同じ集合に属するか否か
    bool same(int x, int y) {
        return (find(x) == find(y));
    }
};

vector<int> compress(vector<pll>& abs, vector<ar3>& lrs) {
    // 座圧
    const int N = abs.size();
    sort(abs.begin(), abs.end());
    for (auto& lr : lrs) {
        ll& l = lr[0];
        ll& r = lr[1];

        // [l,r)
        pll tgtL = make_pair(l, -1);
        pll tgtR = make_pair(r, 2);
        l = upper_bound(abs.begin(), abs.end(), tgtL) - abs.begin();
        r = upper_bound(abs.begin(), abs.end(), tgtR) - abs.begin();
        if (l == r) l = INF;
    }

    sort(lrs.begin(), lrs.end());
    while (!lrs.empty() && lrs.back()[0] == INF)lrs.pop_back();

    vector<int> bs(N);
    rep(i, N)bs[i] = abs[i].second;
    return bs;
}

vector<int> make_difference_sequence(vector<int> bs) {
    // 差分数列化
    vector<int> diffseq;
    bs.insert(bs.begin(), 0);
    bs.push_back(0);
    rep(i, bs.size() - 1)diffseq.push_back(bs[i] != bs[i + 1]);
    return diffseq;
}

vector<SparseGraph> decomposition(const int N, vector<ar3> lrs) {
    // kruskal
    UnionFind uf(N + 1);
    vector<ar3> use;
    for (auto lr : lrs) {
        ll l = lr[0], r = lr[1];
        if (!uf.same(l, r)) {
            uf.unite(l, r);
            use.push_back(lr);
        }
    }
    // klustering
    map<int, vector<ar3>> mp;
    for (auto edge : use) {
        mp[uf.find(edge[0])].push_back(edge);
    }
    vector<SparseGraph> result;
    for (auto itr : mp) {
        SparseGraph graph;
        for (auto edge : itr.second) {
            ll l = edge[0], r = edge[1], idx = edge[2];
            graph[l].push_back({ r,idx });
            graph[r].push_back({ l,idx });
        }
        result.push_back(graph);
    }
    // 単独頂点処理
    map<int, int> par;
    rep(i, N + 1)par[uf.find(i)]++;
    rep(i, N + 1)if (par[i] == 1) {
        SparseGraph graph;
        graph[i].push_back({ i,0 });
        result.push_back(graph);
    }
    return result;
}

bool find_fail_pattern(const SparseGraph& tree, const vector<int>& diffseq) {
    // 単一頂点の処理
    if (tree.size() == 1) {
        return diffseq[tree.begin()->first] == 1;
    }
    int oddCnt = 0;
    for (const auto& itr : tree) {
        oddCnt += diffseq[itr.first];
    }
    return oddCnt % 2 == 1;
}

vector<int> tree_dfs(const SparseGraph& tree, const int now, const int bef, vector<int>& diffseq) {
    vector<int> res;
    for (const auto& next : tree.at(now)) {
        int to, idx;
        tie(to, idx) = next;
        if (to == bef)continue;

        // 孫要素の処理
        auto tres = tree_dfs(tree, to, now, diffseq);
        if (res.size() < tres.size()) {
            swap(res, tres);
        }
        res.insert(res.end(), tres.begin(), tres.end());

        // 子要素の処理
        if (diffseq[to] == 1) {
            diffseq[to] = 0;
            diffseq[now] = (diffseq[now] == 1 ? 0 : 1);
            res.push_back(idx);
        }
    }
    return res;
}

vector<int> bottomup_parity(const SparseGraph& tree, vector<int>& diffseq) {
    int root = tree.begin()->first;
    return tree_dfs(tree, root, -1, diffseq);
}

int main()
{
    // 入力
    ll N, M;
    cin >> N >> M;
    vector<pll> abs(N);
    vector<ar3> lrs(M);
    rep(i, N)cin >> abs[i].first >> abs[i].second;
    rep(i, M) {
        cin >> lrs[i][0] >> lrs[i][1];
        lrs[i][2] = i;
    }

    // 第1段階: 差分数列による森化
    auto bs = compress(abs, lrs);
    auto diffseq = make_difference_sequence(bs);
    auto trees = decomposition(N, lrs);

    // 結果が構成できないときの例外処理
    if (any_of(trees.begin(), trees.end(),
        [&](const SparseGraph& tree) {
        return find_fail_pattern(tree, diffseq);
    })) {
        cout << -1 << endl;
        return 0;
    }

    // 第2段階: 木上でのボトムアップパリティとその復元
    vector<int> cs;
    for (const auto& tree : trees) if (tree.size() != 1) {
        auto result = bottomup_parity(tree, diffseq);
        cs.insert(cs.end(), result.begin(), result.end());
    }
    sort(cs.begin(), cs.end());
    cout << cs.size() << endl;
    for (int c : cs)cout << c + 1 << " ";
    cout << endl;
    return 0;
}


Measured memory_bytes: 45164