#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define FOR(i,k,n) for(int(i)=(k);(i)<(n);++(i))
#define rep(i,n) FOR(i,0,n)
#define all(v) begin(v),end(v)
#define debug(x) std::cerr<<#x<<": "<<x<<"\n"
#define debug2(x,y) std::cerr<<#x<<": "<<x<<", "<<#y<<": "<<y<<"\n"
#define debug3(x,y,z) std::cerr<<#x<<": "<<x<<", "<<#y<<": "<<y<<", "<<#z<<": "<<z<<"\n"

using ll=long long;
using vi=std::vector<int>;
using vvi=std::vector<vi>;
using vll=std::vector<ll>;
using vvll=std::vector<vll>;
template<typename T> std::vector<T> vec(int l,T e){return std::vector<T>(l,e);}
template<typename T> using MaxHeap=std::priority_queue<T>;
template<typename T> using MinHeap=std::priority_queue<T,std::vector<T>,std::greater<T> >;

template<typename T> std::ostream& operator<<(std::ostream&s,const std::vector<T>&v){
  int sz=v.size();s<<"\n";rep(i,sz){s<<v[i];if(i<sz-1){s<<"\t";}}s<<"\n";return s;}
template<typename T> std::ostream& operator<<(std::ostream&s,const std::vector<std::vector<T>>&v){
  for(auto&& w:v){s<<w;}return s;}
template<typename T> std::ostream& operator<<(std::ostream&s,const std::deque<T>&v){
  int sz=v.size();s<<"\n";rep(i,sz){s<<v[i];if(i<sz-1){s<<"\t";}}s<<"\n";return s;}
template<typename T> std::ostream& operator<<(std::ostream&s,const std::deque<std::deque<T>>&v){
  for(auto&& w:v){s<<w;}return s;}
template<typename T> std::ostream& operator<<(std::ostream&s, const std::set<T>&v){
  s<<"\n";for(auto&& elm:v){s<<elm<<"\t";}s<<"\n";return s;}

inline void scan(int&a){scanf("%d",&a);}
inline void scan(ll&a){scanf("%lld",&a);}
inline void scan(char&a){scanf(" %c",&a);}
inline void scan(double&a){scanf("%lf",&a);}
template<typename T>
inline void scan(std::vector<T>&v){for(auto&& sv:v){scan(sv);}}
template<typename First,typename...Args>
inline void scan(First&f,Args&...args){scan(f);scan(args...);}
inline void scan(std::string&s){char BUF[3000000];scanf(" %s",BUF);s=std::string(BUF);}
inline void print(int a){printf("%d\n",a);}
inline void print(ll a){printf("%lld\n",a);}
inline void print(double a){printf("%.12f\n",a);}
inline void print(std::string s){std::cout<<s<<"\n";}

using namespace std;

/*
頂点集合 S とする
D_i に重複が存在する頂点集合 T をとる
S を優先度付きキューに入れ、 D の昇順で以下の処理をして処理済みリストに追加する
{
  頂点 u について、 u を端点に持つ辺のうち、もう一方の端点 v の D_v が D_u よりも大きいものについては保留し、
  それ以外の辺のコストを決定するが、 D_u >= D_v であるような辺が1つも存在しない場合は-1
  v が処理済みであるならば、 u を v とは異なる色で塗り、 辺のコストを D_u とする
  D_u = D_v かつ v が未処理であるならば、 u を適当な色とし、辺の処理は保留する
}
progress
0: それまでに pq に入れられたことがない
1: pq に入っている
2: pq に入れられた後 pop され処理された
*/

void no_sol() {
  print(-1);
  exit(0);
}

void print_sol(vi color, vi weight) {
  int n = color.size();
  rep (i, n) {
    assert (color[i] == 1 || color[i] == 2);
    char c = " WB"[color[i]];
    printf("%c", c);
  }
  printf("\n");
  int m = weight.size();
  rep (i, m) {
    assert (weight[i] > 0);
    print(weight[i]);
  }
}

struct Edge {
  int idx, u, v;
  int opponent(int w) {
    return w ^ u ^ v;
  }
};

int main() {
  int n, m;
  scan(n, m);
  vi d(n);
  scan(d);
  vector<vector<Edge> > edges(n);
  rep (i, m) {
    int u, v;
    scan(u, v);
    --u; --v;
    auto edge = Edge({i, u, v});
    edges[u].push_back(edge);
    edges[v].push_back(edge);
  }
  vvi ds(n, vi(2));
  rep (i, n) {
    ds[i][0] = d[i];
    ds[i][1] = i;
  }
  map<int, int> dcnt;
  rep (i, n) {
    dcnt[d[i]] += 1;
  }

  vi color(n, 0);
  vi weight(m, 0);
  deque<int> progress(n, 0);
  MinHeap<vi> pq;
  vi requirement(n, 0);
  rep (i, n) {
    if (dcnt[ds[i][0]] >= 2) {
      pq.push(ds[i]);
      progress[ds[i][1]] = 1;
    }
  }
  rep (i, n) {
    if (pq.empty()) {
      no_sol();
    }
    auto dsi = pq.top();
    pq.pop();
    int u = dsi[1];
    assert (progress[u] == 1);
    progress[u] = 2;
    bool connectivity = false;
    for (auto edge : edges[u]) {
      int v = edge.opponent(u);
      if (progress[v] == 2 && d[v] <= d[u]) {
        connectivity = true;
        break;
      }
    }
    if (!connectivity) {
      for (auto edge : edges[u]) {
        int v = edge.opponent(u);
        if (progress[v] == 1 && d[v] == d[u]) {
          connectivity = true;
          requirement[u] = 1;
          break;
        }
      }
    }
    if (!connectivity) {
      no_sol();
    }
    color[u] = 1;
    int colors = 0;
    for (auto edge : edges[u]) {
      int v = edge.opponent(u);
      if (progress[v] < 2) {
        continue;
      }
      assert (weight[edge.idx] == 0);
      assert (d[v] <= d[u]);
      weight[edge.idx] = d[u];
      colors |= color[v];
      if (requirement[v] == 1) {
        color[u] = 2;
        requirement[v] = 0;
      }
    }
    if (colors == 1) {
      color[u] = 2;
    }
    for (auto edge : edges[u]) {
      int v = edge.opponent(u);
      if (progress[v] == 0) {
        pq.push({d[v], v});
        progress[v] = 1;
      }
    }
  }
  print_sol(color, weight);

  return 0;
}


Measured memory_bytes: 26804