#include <bits/stdc++.h>
const long long INF = 4e18L + 1;
const int IINF = 2e9 + 1;
const int limit = 1048576;
using namespace std;
bool bs = false;
struct Dinic {
  struct Din_edge {
    int v;
    long long cap;
    int rev_ind;
  };
  int n, source, sink;
  vector<int> starte, d;
  vector<vector<Din_edge> > nei;
  inline bool bfs() {
    d = vector<int>(n + 1, -1);
    d[source] = 0;
    vector<int> q(1, source);
    for (long long i = (long long)0; i < (long long)q.size(); i++) {
      int v = q[i];
      for (auto w : nei[v])
        if (d[w.v] == -1 && w.cap) {
          q.push_back(w.v);
          d[w.v] = d[v] + 1;
        }
    }
    return d[sink] != -1;
  }
  long long dfs(int v, long long mincap) {
    if (!mincap || v == sink) return mincap;
    long long fp = 0;
    for (long long i = (long long)starte[v]; i < (long long)nei[v].size();
         i++) {
      if (!mincap)
        break;
      else
        starte[v] = i;
      Din_edge& edge = nei[v][i];
      int w = nei[v][i].v;
      if (d[w] == d[v] + 1) {
        long long f = dfs(w, min(mincap, edge.cap));
        mincap -= f;
        fp += f;
        edge.cap -= f;
        nei[edge.v][edge.rev_ind].cap += f;
      }
    }
    return fp;
  }
  Dinic(int n, int source, int sink)
      : n(n), source(source), sink(sink), nei(n + 1) {}
  long long flow() {
    long long maxflow = 0;
    while (bfs()) {
      starte = vector<int>(n + 1, 0);
      maxflow += dfs(source, INF);
    }
    return maxflow;
  }
  void add_edge(int from, int to, long long capacity, long long cap2 = 0) {
    Din_edge e1 = (Din_edge){to, capacity, (int)((nei[to]).size())},
             e2 = (Din_edge){from, cap2, (int)((nei[from]).size())};
    nei[from].push_back(e1);
    nei[to].push_back(e2);
  }
  vector<int> find_source_cc() {
    bfs();
    vector<int> ans;
    for (int i = 0; i <= n; i++)
      if (d[i] != -1) ans.push_back(i);
    return ans;
  }
  void wypisz() {
    for (int i = 1; i <= n; i++) {
      cout << i << ": ";
      for (auto el : nei[i]) cout << "(" << el.v << " " << el.cap << ") ";
      cout << endl;
    }
  }
};
struct Edge {
  int a, b;
  long long mini, maxi;
};
vector<pair<int, int> > VV;
int pom;
long long LRMaxFlow(int n, int s, int t, const vector<Edge>& edges) {
  for (auto& el : edges)
    if (el.maxi < el.mini) {
      return -1;
    }
  int big_source = n + 1, big_sink = n + 2;
  Dinic dinic(n + 2, big_source, big_sink);
  vector<long long> du(n + 3, 0);
  long long sum = 0;
  for (auto& el : edges) {
    if (el.mini) {
      du[el.a] -= el.mini;
      du[el.b] += el.mini;
    }
    if (el.mini != el.maxi) dinic.add_edge(el.a, el.b, el.maxi - el.mini);
  }
  if (s != -1) dinic.add_edge(t, s, INF);
  for (int i = 1; i <= n + 2; i++) {
    if (!du[i]) continue;
    if (du[i] < 0)
      dinic.add_edge(i, n + 2, -du[i]);
    else {
      dinic.add_edge(n + 1, i, du[i]);
      sum += du[i];
    }
  }
  long long flow1 = dinic.flow();
  if (flow1 < sum) return -1;
  if (s == -1) return sum;
  dinic.source = s;
  dinic.sink = t;
  long long flow2 = dinic.flow();
  for (int i = 2; i < pom; i++) {
    for (auto& el : dinic.nei[i]) {
      if (el.v <= i || el.v >= n) continue;
      if (el.cap == 0) VV.push_back({i, el.v});
    }
  }
  return flow2;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  long long n, m, r, b;
  cin >> n >> m >> r >> b;
  vector<pair<int, int> > V;
  map<int, int> X, Y;
  vector<Edge> edges;
  for (int i = 0; i < n; i++) {
    int x, y;
    cin >> x >> y;
    V.push_back({x, y});
    X[x]++;
    Y[y]++;
  }
  int nr = 2, ilex, iley;
  for (auto& el : X) el.second = nr++;
  ilex = nr - 2;
  for (auto& el : Y) el.second = nr++;
  iley = nr - ilex - 2;
  pom = 2 + ilex;
  vector<int> abs_d(nr + 1, IINF), cnt(nr, 0);
  for (auto el : V) {
    int x = X[el.first], y = Y[el.second];
    edges.push_back((Edge){x, y, 0, 1});
    cnt[x]++;
    cnt[y]++;
  }
  while (m--) {
    int a, b, c;
    cin >> a >> b >> c;
    if (a == 1) {
      if (X.find(b) == X.end()) continue;
      int ind = X[b];
      abs_d[ind] = min(abs_d[ind], c);
    } else {
      if (Y.find(b) == Y.end()) continue;
      int ind = Y[b];
      abs_d[ind] = min(abs_d[ind], c);
    }
  }
  for (int i = 2; i < 2 + ilex; i++) {
    if (cnt[i] <= abs_d[i]) {
      edges.push_back({1, i, 0, cnt[i]});
      continue;
    }
    int maxi = (cnt[i] + abs_d[i]) / 2;
    edges.push_back({1, i, cnt[i] - maxi, maxi});
  }
  for (int i = 2 + ilex; i < 2 + ilex + iley; i++) {
    if (cnt[i] <= abs_d[i]) {
      edges.push_back({i, 2 + ilex + iley, 0, cnt[i]});
      continue;
    }
    int maxi = (cnt[i] + abs_d[i]) / 2;
    edges.push_back({i, 2 + ilex + iley, cnt[i] - maxi, maxi});
  }
  long long ans = LRMaxFlow(2 + ilex + iley, 1, 2 + ilex + iley, edges);
  if (ans == -1) {
    cout << "-1";
  } else {
    cout << ans * min(r, b) + (n - ans) * max(r, b) << "\n";
    assert(ans == VV.size());
    char rr = 'r', bb = 'b';
    if (r > b) swap(rr, bb);
    map<pair<int, int>, int> Map;
    for (auto el : VV) Map[el]++;
    int ile = 0;
    for (auto& el : V) {
      int x = X[el.first], y = Y[el.second];
      int& zostalo = Map[{x, y}];
      if (zostalo) {
        cout << rr;
        zostalo--;
        ile++;
      } else
        cout << bb;
    }
    assert(ile == VV.size());
  }
  return 0;
}
