#include <bits/stdc++.h>
using namespace std;
class Tree {
 public:
  int nodes;
  int root = 0;
  vector<vector<int> > adjacency_graph;
  vector<int> par;
  vector<int> depth;
  Tree(int nodes) : nodes(nodes) { adjacency_graph.resize(nodes); }
  Tree(int nodes, int root) : Tree(nodes) { this->root = root; }
  void addEdge(int u, int v, bool decrement_identifier = false) {
    if (decrement_identifier) {
      u--;
      v--;
    }
    assert(u < nodes and v < nodes);
    adjacency_graph[u].push_back(v);
    adjacency_graph[v].push_back(u);
  }
  template <typename T, typename U>
  void dfs(int u, int parent, T pre_func, U post_func) {
    for (auto v : adjacency_graph[u])
      if (v != parent) {
        pre_func(u, v);
        dfs(v, u, pre_func, post_func);
        post_func(u, v);
      }
  }
  void processParents() {
    par.resize(nodes);
    auto parent_lambda = [this](int parent, int node) { par[node] = parent; };
    dfs(root, root, parent_lambda, [](int u, int v) {});
  }
  void processDepth() {
    depth.resize(nodes);
    depth[root] = 0;
    auto depth_lambda = [this](int parent, int node) {
      depth[node] = depth[parent] + 1;
    };
    dfs(root, root, depth_lambda, [](int u, int v) {});
  }
  int getParent(int u) {
    assert(u < nodes);
    return par[u];
  }
  int getDepth(int u) {
    assert(u < nodes);
    return depth[u];
  }
};
class CentroidDecomposition {
 private:
  vector<bool> is_active;
  vector<int> curr_subtree_sizes;

 public:
  Tree* tree;
  vector<int> centroid_tree_par;
  CentroidDecomposition(Tree* tree) : tree(tree) {
    is_active.resize(tree->nodes, true);
    curr_subtree_sizes.resize(tree->nodes, 0);
    centroid_tree_par.resize(tree->nodes);
  }
  void compute_subtree_sizes(int node, int parent) {
    curr_subtree_sizes[node] = 1;
    for (auto v : tree->adjacency_graph[node])
      if (v != parent and is_active[v]) {
        compute_subtree_sizes(v, node);
        curr_subtree_sizes[node] += curr_subtree_sizes[v];
      }
  }
  int findCentroid(int root) {
    compute_subtree_sizes(root, root);
    int current_tree_size = curr_subtree_sizes[root];
    function<int(int, int)> dfs = [&](int node, int parent) {
      for (auto v : tree->adjacency_graph[node])
        if (v != parent and is_active[v])
          if (curr_subtree_sizes[v] > current_tree_size / 2)
            return dfs(v, node);
      return node;
    };
    return dfs(root, root);
  }
  void decompose() {
    function<void(int, int)> recursive_decompose = [&](int root, int parent) {
      int centroid = findCentroid(root);
      is_active[centroid] = false;
      centroid_tree_par[centroid] = parent;
      for (auto v : tree->adjacency_graph[centroid])
        if (is_active[v]) recursive_decompose(v, centroid);
      is_active[centroid] = true;
    };
    recursive_decompose(0, -1);
  }
};
int main() {
  int n;
  cin >> n;
  Tree* tree = new Tree(n);
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    tree->addEdge(u, v, true);
  }
  CentroidDecomposition CD = CentroidDecomposition(tree);
  CD.decompose();
  Tree* decomposed_tree = new Tree(n);
  for (int i = 0; i < n; i++)
    if (CD.centroid_tree_par[i] != -1)
      decomposed_tree->addEdge(i, CD.centroid_tree_par[i]);
    else
      decomposed_tree->root = i;
  decomposed_tree->processDepth();
  for (int i = 0; i < n; i++)
    cout << static_cast<char>('A' + decomposed_tree->getDepth(i)) << " ";
  cout << endl;
  return 0;
}
