#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;
using vpii = vector<pii>;
using vvpii = vector<vpii>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
using vpdd = vector<pdd>;
using vvpdd = vector<vpdd>;
template <typename T>
void ckmin(T& a, const T& b) {
  a = min(a, b);
}
template <typename T>
void ckmax(T& a, const T& b) {
  a = max(a, b);
}
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
namespace __input {
template <class T1, class T2>
void re(pair<T1, T2>& p);
template <class T>
void re(vector<T>& a);
template <class T, size_t SZ>
void re(array<T, SZ>& a);
template <class T>
void re(T& x) {
  cin >> x;
}
void re(double& x) {
  string t;
  re(t);
  x = stod(t);
}
template <class Arg, class... Args>
void re(Arg& first, Args&... rest) {
  re(first);
  re(rest...);
}
template <class T1, class T2>
void re(pair<T1, T2>& p) {
  re(p.first, p.second);
}
template <class T>
void re(vector<T>& a) {
  for (int i = 0; i < (int((a).size())); i++) re(a[i]);
}
template <class T, size_t SZ>
void re(array<T, SZ>& a) {
  for (int i = 0; i < (SZ); i++) re(a[i]);
}
}  // namespace __input
using namespace __input;
namespace __output {
template <class T1, class T2>
void pr(const pair<T1, T2>& x);
template <class T, size_t SZ>
void pr(const array<T, SZ>& x);
template <class T>
void pr(const vector<T>& x);
template <class T>
void pr(const deque<T>& x);
template <class T>
void pr(const set<T>& x);
template <class T1, class T2>
void pr(const map<T1, T2>& x);
template <class T>
void pr(const T& x) {
  cout << x;
}
template <class Arg, class... Args>
void pr(const Arg& first, const Args&... rest) {
  pr(first);
  pr(rest...);
}
template <class T1, class T2>
void pr(const pair<T1, T2>& x) {
  pr("{", x.first, ", ", x.second, "}");
}
template <class T, bool pretty = true>
void prContain(const T& x) {
  if (pretty) pr("{");
  bool fst = 1;
  for (const auto& a : x) pr(!fst ? pretty ? ", " : " " : "", a), fst = 0;
  if (pretty) pr("}");
}
template <class T>
void pc(const T& x) {
  prContain<T, false>(x);
  pr("\n");
}
template <class T, size_t SZ>
void pr(const array<T, SZ>& x) {
  prContain(x);
}
template <class T>
void pr(const vector<T>& x) {
  prContain(x);
}
template <class T>
void pr(const deque<T>& x) {
  prContain(x);
}
template <class T>
void pr(const set<T>& x) {
  prContain(x);
}
template <class T1, class T2>
void pr(const map<T1, T2>& x) {
  prContain(x);
}
void ps() { pr("\n"); }
template <class Arg>
void ps(const Arg& first) {
  pr(first);
  ps();
}
template <class Arg, class... Args>
void ps(const Arg& first, const Args&... rest) {
  pr(first, " ");
  ps(rest...);
}
}  // namespace __output
using namespace __output;
namespace __algorithm {
template <typename T>
void dedup(vector<T>& v) {
  sort((v).begin(), (v).end());
  v.erase(unique((v).begin(), (v).end()), v.end());
}
template <typename T>
typename vector<T>::iterator find(vector<T>& v, const T& x) {
  auto it = lower_bound((v).begin(), (v).end(), x);
  return it != v.end() && *it == x ? it : v.end();
}
template <typename T>
size_t index(vector<T>& v, const T& x) {
  auto it = find(v, x);
  assert(it != v.end() && *it == x);
  return it - v.begin();
}
template <typename C, typename T, typename OP>
vector<T> prefixes(const C& v, T id, OP op) {
  vector<T> r(int((v).size()) + 1, id);
  for (int i = 0; i < (int((v).size())); i++) r[i + 1] = op(r[i], v[i]);
  return r;
}
template <typename C, typename T, typename OP>
vector<T> suffixes(const C& v, T id, OP op) {
  vector<T> r(int((v).size()) + 1, id);
  for (int i = (int((v).size())) - 1; i >= 0; i--) r[i] = op(v[i], r[i + 1]);
  return r;
}
}  // namespace __algorithm
using namespace __algorithm;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
struct monostate {
  friend istream& operator>>(istream& is, const monostate& ms) { return is; }
  friend ostream& operator<<(ostream& os, const monostate& ms) { return os; }
  friend monostate operator+(const monostate& a, const monostate& b) {
    return a;
  }
} ms;
#pragma GCC diagnostic pop
namespace __io {
void setIn(string second) { freopen(second.c_str(), "r", stdin); }
void setOut(string second) { freopen(second.c_str(), "w", stdout); }
void setIO(string second = "") {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(15);
  if (int((second).size())) {
    setIn(second + ".in"), setOut(second + ".out");
  }
}
}  // namespace __io
using namespace __io;
struct union_find {
  struct node {
    int par, rnk, size;
    vi elts;
    node(int id = 0) : par(id), rnk(0), size(1), elts({id}) {}
    template <typename F>
    void merge(node& o, F proc) {
      proc(par, o.par);
      if (rnk == o.rnk) rnk++;
      size += o.size;
      if (int((elts).size()) < int((o.elts).size())) swap(elts, o.elts);
      elts.insert(elts.end(), (o.elts).begin(), (o.elts).end());
    }
  };
  vector<node> uf;
  union_find(int N = 0) : uf(N) {
    for (int i = 0; i < N; i++) {
      uf[i] = node(i);
    }
  }
  int rep(int i) {
    if (i != uf[i].par) uf[i].par = rep(uf[i].par);
    return uf[i].par;
  }
  template <typename F = function<void(int, int)>>
  bool unio(
      int a, int b, F proc = [](int a, int b) {}) {
    a = rep(a), b = rep(b);
    if (a == b) return false;
    if (uf[a].rnk < uf[b].rnk) swap(a, b);
    uf[a].merge(uf[b], proc);
    uf[b].par = a;
    return true;
  }
  node& operator[](int i) { return uf[rep(i)]; }
  friend void pr(const union_find& u) {
    pr("{");
    bool first = 1;
    for (int i = 0; i < int((u.uf).size()); i++)
      if (u.uf[i].par == i) {
        if (!first)
          pr(", ");
        else
          first = 0;
        pr("[ ", i, " | rank=", u.uf[i].rnk, " size=", u.uf[i].size,
           " elts=", u.uf[i].elts, "]");
      }
    pr("}");
  }
};
int main() {
  setIO();
  int N, M;
  re(N, M);
  vi d(N);
  re(d);
  struct edge {
    int u, v;
  };
  vector<edge> edges(M);
  vi eqs;
  vvpii adj(N);
  for (int ei = 0; ei < (M); ei++) {
    edge& e = edges[ei];
    re(e.u, e.v), --e.u, --e.v;
    adj[e.u].emplace_back(e.v, ei);
    adj[e.v].emplace_back(e.u, ei);
    if (d[e.u] == d[e.v]) eqs.push_back(ei);
  }
  union_find uf(N);
  vb done(N, false);
  vi color(N, 0), weight(M, 1e9);
  for (auto& ei : eqs) {
    edge e = edges[ei];
    uf.unio(e.u, e.v, [&](int a, int b) {
      weight[ei] = d[e.u];
      done[e.u] = done[e.v] = 1;
      if (color[e.u] == color[e.v]) {
        if (int((uf.uf[a].elts).size()) > int((uf.uf[b].elts).size()))
          swap(a, b);
        for (auto& n : uf.uf[b].elts) color[n] = !color[n];
      }
    });
  }
  for (int u = 0; u < (N); u++)
    if (!done[u]) {
      for (auto& e : adj[u])
        if (d[e.first] < d[u]) {
          done[u] = 1;
          color[u] = color[e.first];
          weight[e.second] = d[u] - d[e.first];
        }
    }
  if (*min_element((done).begin(), (done).end()) == 0)
    ps(-1);
  else {
    for (auto& e : color) pr(e ? 'W' : 'B');
    ps();
    for (auto& w : weight) ps(w);
  }
  return 0;
}
