#include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;
//const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

struct UnionFind {
  vector< int > data;

  UnionFind(int sz) {
    data.assign(sz, -1);
  }

  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if(x == y) return (false);
    if(data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }

  int find(int k) {
    if(data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }

  int size(int k) {
    return (-data[find(k)]);
  }
};


struct Bipartite_Graph : UnionFind {
  vector< int > color;

  Bipartite_Graph(int v) : color(v + v, -1), UnionFind(v + v) {}

  bool bipartite_graph_coloring() {
    for(int i = 0; i < color.size() / 2; i++) {
      int a = find(i);
      int b = find(i + (int) color.size() / 2);
      if(a == b) return (false);
      if(color[a] < 0) color[a] = 0, color[b] = 1;
    }
    return (true);
  }

  bool operator[](int k) {
    return (bool(color[find(k)]));
  }
};


int main() {
  int N, M;
  cin >> N >> M;
  vector< int > D(N);
  cin >> D;
  // Dがunique → 自明に-1
  // 複数あるやつのうち最小を x とする
  // x 未満のD[i]がある → -1
  // それ以外の場合 → わからん

  // uとvは直接繋がれている必要がある (途中に別の色があったら短くなる)
  // 繋がれていない → -1

  // 単調増加な有向全域木?をとって終わり？
  map< int, vector< int > > be;
  for(int i = 0; i < N; i++) {
    be[D[i]].emplace_back(i);
  }

  if(be.begin()->second.size() == 1) {
    cout << -1 << endl;
    exit(0);
  }

  vector< int > U(M), V(M);
  vector< vector< pair< int, int > > > edge(N);
  for(int i = 0; i < M; i++) {
    cin >> U[i] >> V[i];
    --U[i], --V[i];
    edge[U[i]].emplace_back(V[i], i);
    edge[V[i]].emplace_back(U[i], i);
  }

  vector< int > enable(N);
  for(auto &p : be.begin()->second) enable[p] = true;
  vector< int > C(M, 1000000000);
  UnionFind uf(N);
  Bipartite_Graph bp(N);
  for(int i = 0; i < M; i++) {
    if(enable[U[i]] && enable[V[i]] && uf.unite(U[i], V[i])) {
      C[i] = be.begin()->first;
      bp.unite(U[i], V[i] + N);
      bp.unite(V[i], U[i] + N);
    }
  }
  for(auto &p : be.begin()->second) {
    if(uf.size(p) == 1) {
      cout << -1 << endl;
      exit(0);
    }
  }
  vector< int > color(N, -1);
  assert(bp.bipartite_graph_coloring());
  for(auto &p : be.begin()->second) color[p] = bp[p];
  using pi = pair< int, int >;
  priority_queue< pi, vector< pi >, greater<> > que;
  for(auto &p : be.begin()->second) que.emplace(be.begin()->first, p);

  while(que.size()) {
    auto p = que.top();
    que.pop();
    for(auto &to : edge[p.second]) {
      if(color[to.first] == -1 && p.first < D[to.first]) {
        color[to.first] = color[p.second];
        C[to.second] = D[to.first] - p.first;
        que.emplace(D[to.first], to.first);
      }
    }
  }
  for(auto &p : color) {
    if(p == -1) {
      cout << -1 << endl;
      exit(0);
    }
  }
  for(auto &p : color) {
    if(p) cout << "B";
    else cout << "W";
  }
  cout << "\n";
  for(auto &p : C) cout << p << "\n";
}