#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
string to_string(char c) { return string(1, c); }
string to_string(bool b) { return b ? "true" : "false"; }
string to_string(const char* s) { return (string)s; }
string to_string(string s) { return s; }
template <class T>
string to_string(T v) {
  string res = "";
  for (const auto& x : v) res += to_string(x) + " ";
  if (res.size()) res.pop_back();
  return res;
}
template <class A>
void pr(A x) {
  cout << to_string(x);
}
template <class H, class... T>
void pr(const H& h, const T&... t) {
  pr(h);
  pr(t...);
}
void ps() { pr("\n"); }
template <class H, class... T>
void ps(const H& h, const T&... t) {
  pr(h);
  if (sizeof...(t)) pr(" ");
  ps(t...);
}
class number_iterator {
 public:
  int v;
  int inc;
  number_iterator(int v, int inc = 1) : v(v), inc(inc) {}
  operator int&() { return v; }
  long long operator*() { return v; }
  number_iterator operator++() { return v += inc; }
};
class range : pii {
  int inc;
  void init(int inc = 1) {
    this->second = max(this->first, this->second);
    int div = (this->second - this->first) / inc;
    if ((this->second - this->first) % inc != 0) div += 1;
    this->second = this->first + div * inc;
  }
  void init_dec(int dec = 1) {
    this->first = max(this->first, this->second);
    int div = (this->first - this->second) / dec;
    if ((this->first - this->second) % dec != 0) div += 1;
    this->second = this->first - div * dec;
  }

 public:
  range(int first, int second, int inc = 1) : pii(first, second), inc(inc) {
    if (inc < 0)
      init_dec(-inc);
    else
      init(inc);
  }
  range(int n) : range(0, n, 1) {}
  number_iterator begin() { return number_iterator(first, inc); }
  number_iterator end() { return number_iterator(second, inc); }
};
class graph {
 public:
  struct edge {
    int from;
    int to;
  };

 protected:
  int n;

 public:
  vector<vector<int>> g;
  vector<edge> edges;
  graph(int n) : n(n) { g.resize(n); }
  void add(int from, int to) {
    g[from].push_back(edges.size());
    edges.push_back({from, to});
  }
};
class tree : public graph {
  void do_dfs(int v) {
    if (color[v] == 1) {
      cycle = true;
      return;
    }
    color[v] = 1;
    for (auto id : g[v]) {
      edge& e = edges[id];
      int to = e.from ^ e.to ^ v;
      if (color[to] != 2) do_dfs(to);
    }
    color[v] = 2;
    topology.push_front(v);
  }

 public:
  tree(int _n) : graph(_n) {}
  vector<int> color;
  deque<int> topology;
  bool cycle = false;
  void init_dfs() { color.resize(n, 0); }
  void dfs(int start = 0) { do_dfs(start); }
};
void solve() {
  int n, m;
  cin >> n >> m;
  tree g(n);
  vector<int> in_count(n, 0);
  for (int i : range(m)) {
    int u, v;
    cin >> u >> v;
    g.add(--u, --v);
    in_count[v]++;
  }
  g.init_dfs();
  for (int i : range(n))
    if (!in_count[i]) g.dfs(i);
  if (g.cycle) return ps("-1");
  for (int i : range(n))
    if (in_count[i] > 0 && !g.color[i]) return ps("-1");
  vector<int> min_up(n), min_down(n);
  for (int i : range(n)) min_up[i] = min_down[i] = i;
  for (auto i : g.topology)
    for (auto id : g.g[i]) {
      auto e = g.edges[id];
      int to = e.from ^ e.to ^ i;
      min_up[to] = min(min_up[i], min_up[to]);
    }
  reverse(g.topology.begin(), g.topology.end());
  for (auto i : g.topology)
    for (auto id : g.g[i]) {
      auto e = g.edges[id];
      int to = e.from ^ e.to ^ i;
      min_down[i] = min(min_down[i], min_down[to]);
    }
  string res;
  int cnt = 0;
  for (int i : range(n)) {
    if (min_up[i] == i && min_down[i] == i) {
      res += 'A';
      cnt++;
    } else
      res += 'E';
  }
  ps(cnt);
  ps(res);
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  solve();
}
