#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using V = vector<int>;
using Vll = vector<ll>;
using Vld = vector<ld>;
using Vbo = vector<bool>;
using VV = vector<V>;
using VVll = vector<Vll>;
using VVld = vector<Vld>;
using VVbo = vector<Vbo>;
using VVV = vector<VV>;
using VVVll = vector<VVll>;
using P = pair<int, int>;
using Pll = pair<ll, ll>;
using Pld = pair<ld, ld>;
#define rep2(i, m, n) for (int i = (m); i < (n); ++i)
#define drep2(i, m, n) for (int i = (m)-1; i >= (n); --i)
#define rep(i, n) rep2(i, 0, n)
#define drep(i, n) drep2(i, n, 0)
#define all(a) (a).begin(), (a).end()
struct fast_ios { fast_ios(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
template<typename T> inline int sz(T &x) { return x.size(); }
template<typename T> inline bool chmin(T &a, T b) { if (a > b) { a = b; return true; } return false; }
template<typename T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return true; } return false; }
template<typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }
template<typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p) { os << '(' << p.first << ", " << p.second << ')'; return os; }
template<typename T> istream &operator>>(istream &is, vector<T> &v) { for (auto &e : v) is >> e; return is; }
template<typename T> ostream &operator<<(ostream &os, const vector<T> &v) { for (auto &e : v) os << e << ' '; return os; }
template<typename T> inline int count_between(vector<T> &a, T l, T r) { return lower_bound(all(a), r) - lower_bound(all(a), l); } // [l, r)
inline int fLog2(const int x) { assert(x > 0); return 31-__builtin_clz(x); } // floor(log2(x))
inline int fLog2(const ll x) { assert(x > 0); return 63-__builtin_clzll(x); }
inline int cLog2(const int x) { assert(x > 0); return (x == 1) ? 0 : 32-__builtin_clz(x-1); } // ceil(log2(x))
inline int cLog2(const ll x) { assert(x > 0); return (x == 1) ? 0 : 64-__builtin_clzll(x-1); }
inline int popcount(const int x) { return __builtin_popcount(x); }
inline int popcount(const ll x) { return __builtin_popcountll(x); }
void fail() { puts("-1"); exit(0); }
// const int INF  = 1<<30;
// const ll INFll = 1ll<<62;
// const ld EPS   = 1e-10;
// const ld PI    = acos(-1.0);
// const int MOD  = int(1e9)+7;
// const int MOD  = 998244353;


VV G;
V cl;

bool dfs(int u, int x = 0) {
  if (cl[u] == x) return true;
  if (cl[u] == (x^1)) return false;
  cl[u] = x;
  bool res = true;
  for (auto v : G[u]) res &= dfs(v, x^1);
  return res;
}


// edges
template<typename T>
struct edge {
  int u, v; T w;
  edge(int u, int v, T w) : u(u), v(v), w(w) {}
};
template<typename T>
using Edges = vector<edge<T>>;


// union-find
struct UnionFind {
  vector<int> d;
  UnionFind(int n=0): d(n, -1) {}
  int find(int x) {
    if (d[x] < 0) return x;
    return d[x] = find(d[x]);
  }
  bool unite(int x, int y) {
    x = find(x); y = find(y);
    if (x == y) return false;
    if (d[x] > d[y]) swap(x,y);
    d[x] += d[y];
    d[y] = x;
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y);}
  int size(int x) { return -d[find(x)];}
};


// main algorithm
template<typename T>
T kruskal(Edges<T> &E, int N) {
  sort(begin(E), end(E), [](const edge<T> &a, const edge<T> &b) { return (a.w < b.w); });
  UnionFind uf(N);
  T res = 0;
  for (auto &[u, v, w] : E) if (uf.unite(u, v)) {
    res += w;
    G[u].push_back(v);
    G[v].push_back(u);
  }
  return res;
}


int main() {
  int n, m; cin >> n >> m;
  V d(n); cin >> d;
  G.assign(n, V());

  Edges<ll> E;
  V w(m);
  Vbo ok(n);

  rep(i, m) {
    int u, v; cin >> u >> v;
    --u, --v;
    w[i] = max(d[u], d[v]);
    E.emplace_back(u, v, w[i]);
    if (d[u] >= w[i]) ok[u] = true;
    if (d[v] >= w[i]) ok[v] = true;
  }

  rep(i, n) if (!ok[i]) fail();

  kruskal(E, n);
  cl.assign(n, -1);
  dfs(0);

  rep(i, n) cout << (cl[i] == 0 ? 'B' : 'W');
  cout << '\n';
  cout << w << '\n';
  return 0;
}


Measured memory_bytes: 14824