Problem:
Problem H: RGBtree
Problem
$N$ 頂点 $N-1$ 辺からなる木があり、頂点には $1,2,\ldots,N$ の番号が、辺には $1,2,\ldots,N-1$ の番号がついており、 $i$ 番目の辺は頂点 $a_i$ と 頂点 $b_i$
	を繋ぎます。
カトー君は、赤、緑、青の三色を用いてこの木の全ての頂点に色をつけます。
以下、'R' で赤、'G' で緑、'B' で青を表します。
あるパスに含まれる赤色で塗られた頂点の個数を $r$ 、緑色で塗られた頂点の個数を $g$ 、青色で塗られた頂点の個数を $b$ としたとき、 $\max (r,g,b)$ をそのパスのペナルティと定義します。
木全体のペナルティを「その木に含まれる、全てのパスのペナルティの最大値」と定義します。
あなたは、与えられた木に適切に色をつけた場合ペナルティの最小値はいくつになるか、カトー君の代わりに計算してあげることにしました。
ペナルティの最小値を求めてください。
また、そのペナルティを実現する色のつけ方を1つ求めてください。
複数の色のつけ方が存在する場合、どれを出力しても構いません。
Constraints
入力は以下の条件を満たす。
$1 \leqq N \leqq 2 \times 10^{5}$
$1 \leqq a_i, b_i \leqq N$
与えられるグラフは木であることが保証される。
入力は全て整数である。
Input
入力は以下の形式で標準入出力から与えられる。
$N$
$a_1$ $b_1$
$a_2$ $b_2$
$\vdots$
$a_{N-1}$ $b_{N-1}$
Output
非負整数 $X$ 、文字列 $S$ を以下の形式で出力せよ。
ただし、 $X$ は達成可能な木全体のペナルティの最小値である。
$S$ は $i$ 文字目 $(1 \leqq i \leqq N)$ が頂点 $i$ の色を表す、ペナルティ $X$ を達成する塗り方を表す長さ $N$ の文字列である。
$S$ は、'R','G','B' の文字以外を含んではならない。
$X$
$S$
末尾の改行を忘れないこと。
Sample Input 1
4
1 2
2 3
3 4
Sample Output 1
2
RGBR
この塗り方では、頂点1から頂点4までのパスのペナルティが一番大きく、最も多く含まれるのは 'R' で2個です。
よって、この木のペナルティは2で、これ以上ペナルティを小さくすることはできないため、 $X=2$ が答えになります。
$S$ としては他にも、 "RRBG" や "GGBB" といったものが正解として考えられます。
Sample Input 2
6
1 2
2 3
2 4
4 5
4 6
Sample Output 2
2
RGBRGB
どのように色を塗ってもペナルティを2より小さくすることはできません。
$S$ としては他にも、 "RRGGBB" といったものが正解として考えられます。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

int n;
vector<vector<int>> g;
string res, col = "RGB";

vector<int> search_diameter();
void mod_coloring(int now, int par, int dist, int ad = 1);
int calc_dist(int now, int par, int dist);
int solve();

int main() {
  cin >> n;
  g.resize(n);
  res = string(n, '-');
  for (int i = 1; i < n; ++i) {
    int a, b;
    cin >> a >> b;
    g[--a].push_back(--b);
    g[b].push_back(a);
  }
  cout << solve() << endl;
  cout << res << endl;
  return 0;
}

vector<int> search_diameter() {
  vector<int> par;
  int root = 0;
  for (int i = 0; i < 2; ++i) {
    queue<int> qu;
    qu.push(root);
    par.assign(n, -2);
    par[root] = -1;
    while (qu.size()) {
      int now = qu.front();
      root = now;
      qu.pop();
      for (auto to : g[now])
        if (par[to] == -2) {
          par[to] = now;
          qu.push(to);
        }
    }
  }
  vector<int> v;
  while (root != -1) {
    v.push_back(root);
    root = par[root];
  }
  return v;
}

void mod_coloring(int now, int par, int dist, int ad) {
  res[now] = col[dist];
  for (auto to : g[now])
    if (to != par) mod_coloring(to, now, (dist + ad + 3) % 3, ad);
}

int calc_dist(int now, int par, int dist) {
  int res = dist;
  for (auto to : g[now])
    if (to != par) res = max(res, calc_dist(to, now, dist + 1));
  return res;
}

int solve() {
  auto dpath = search_diameter();
  int d = dpath.size();
  if (d & 1) {
    if (d % 3) {
      mod_coloring(0, -1, 0);
      return (d + 2) / 3;
    } else {  // check
      int cnt = 0, root = dpath[d / 2];
      mod_coloring(root, -1, 0);
      mod_coloring(dpath[d / 2 - 1], root, 2, -1);
      for (auto to : g[root])
        if (calc_dist(to, root, 1) == d / 2) ++cnt;
      return (d + 2 + (cnt >= 3)) / 3;
    }
  } else {
    mod_coloring(dpath[d / 2], dpath[d / 2 - 1], 0);
    mod_coloring(dpath[d / 2 - 1], dpath[d / 2], 2, -1);
    return (d + 2) / 3;
  }
  return -1;
}
accuracy: 1
time_ms: 90
memory_kb: 27628
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

int N;
vector<vector<int>> g;

int findFar(int st){
  queue<int> Q;
  vector<int> dist(N,MOD);
  dist[st]=0;
  Q.push(st);
  while(!Q.empty()){
    int now=Q.front();Q.pop();
    for(auto nex:g[now]){
      if(dist[nex]==MOD){
        dist[nex]=dist[now]+1;
        Q.push(nex);
      }
    }
  }
  int fat=0;
  rep(i,N) if(dist[i]>dist[fat]) fat=i;
  return fat;
}

bool dfs(int now,int par,int goal,vector<int> &v){
  if(now==goal){
    v.push_back(now);
    return true;
  }
  for(auto nex:g[now]) if(nex!=par){
    if(dfs(nex,now,goal,v)){
      v.push_back(now);
      return true;
    }
  }
  return false;
}

vector<int> getDiameter(){
  int st=findFar(0);
  st=findFar(st);
  int ed=findFar(st);
  vector<int> path;
  dfs(st,-1,ed,path);
  return path;
}

vector<int> getdist(int st,int ed){
    vector<int> dist(N,MOD);
    dist[st]=0;
    dist[ed]=0;
    queue<int> Q;
    Q.push(st);
    if(ed!=st) Q.push(ed);
    while(!Q.empty()){
        int now=Q.front();Q.pop();
        for(auto nex:g[now]){
                if(dist[nex]==MOD){
                    dist[nex]=dist[now]+1;
                    Q.push(nex);
            }
        }
    }
    return dist;
}

bool dfs(int now,int par,int d,int goal){
    if(d==goal) return true;
    for(auto nex:g[now]){
        if(nex!=par){
            if(dfs(nex,now,d+1,goal)) return true;
        }
    }
    return false;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N;
  g.resize(N);
  rep(i,N-1){
    int a,b;
    cin>>a>>b;
    a--;b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }

  vector<int> diameter=getDiameter();
  int D=diameter.size();
  if(D%3){
    int st=diameter[D/2];
    vector<int> dist=getdist(st,st);

    string ans="";
    rep(i,N){
      dist[i]%=3;
      if(dist[i]==0) ans+='R';
      else if(dist[i]==1) ans+='G';
      else ans+='B';
    }
    cout<<D/3+1<<"\n";
    cout<<ans<<"\n";
    return 0;
  }

  if(D%2==0){
    int st=diameter[D/2-1];
    int ed=diameter[D/2];
    vector<int> dist=getdist(st,ed);

    string ans="";
    rep(i,N){
      dist[i]%=3;
      if(dist[i]==0) ans+='R';
      else if(dist[i]==1) ans+='G';
      else ans+='B';
    }
    cout<<D/3<<"\n";
    cout<<ans<<"\n";
    return 0;
  }

  {
    int st=diameter[D/2];
    vector<int> dist=getdist(st,st);
    int ma=*max_element(all(dist));

    int masubg=0;
    for(auto nex:g[st]){
        if(dfs(nex,st,1,ma)) masubg++;
    }

    if(masubg>2){
        cout<<D/3+1<<"\n";

        st=diameter[D/2];
        dist=getdist(st,st);

        string ans="";
        rep(i,N){
            dist[i]%=3;
            if(dist[i]==0) ans+='R';
            else if(dist[i]==1) ans+='G';
            else ans+='B';
        }
        cout<<ans<<"\n";
        return 0;
    }else{
        cout<<D/3<<"\n";

        st=diameter[D/2];
        int fir=diameter[D/2-1];
        int sec=diameter[D/2+1];
        vector<int> dist(N,MOD);
        queue<int> Q;
        Q.push(st);Q.push(fir);Q.push(sec);
        dist[st]=0;dist[fir]=1;dist[sec]=2;
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            for(auto nex:g[now]){
                if(dist[nex]==MOD){
                    dist[nex]=dist[now]+1;
                    dist[nex]%=3;
                    Q.push(nex);
                }
            }
        }

        string ans="";
        rep(i,N){
            dist[i]%=3;
            if(dist[i]==0) ans+='R';
            else if(dist[i]==1) ans+='G';
            else ans+='B';
        }
        cout<<ans<<"\n";
    }
    return 0;
  }

  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 28428
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

int N;
vector<vector<int>> g;

int findFar(int st){
  queue<int> Q;
  vector<int> dist(N,MOD);
  dist[st]=0;
  Q.push(st);
  while(!Q.empty()){
    int now=Q.front();Q.pop();
    for(auto nex:g[now]){
      if(dist[nex]==MOD){
        dist[nex]=dist[now]+1;
        Q.push(nex);
      }
    }
  }
  int fat=0;
  rep(i,N) if(dist[i]>dist[fat]) fat=i;
  return fat;
}

bool dfs(int now,int par,int goal,vector<int> &v){
  if(now==goal){
    v.push_back(now);
    return true;
  }
  for(auto nex:g[now]) if(nex!=par){
    if(dfs(nex,now,goal,v)){
      v.push_back(now);
      return true;
    }
  }
  return false;
}

vector<int> getDiameter(){
  int st=findFar(0);
  st=findFar(st);
  int ed=findFar(st);
  vector<int> path;
  dfs(st,-1,ed,path);
  return path;
}

vector<int> getdist(int st,int ed){
    vector<int> dist(N,MOD);
    dist[st]=0;
    dist[ed]=0;
    queue<int> Q;
    Q.push(st);
    if(ed!=st) Q.push(ed);
    while(!Q.empty()){
        int now=Q.front();Q.pop();
        for(auto nex:g[now]){
                if(dist[nex]==MOD){
                    dist[nex]=dist[now]+1;
                    Q.push(nex);
            }
        }
    }
    return dist;
}

bool dfs(int now,int par,int d,int goal){
    if(d==goal) return true;
    for(auto nex:g[now]){
        if(nex!=par){
            if(dfs(nex,now,d+1,goal)) return true;
        }
    }
    return false;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin>>N;
  g.resize(N);
  rep(i,N-1){
    int a,b;
    cin>>a>>b;
    a--;b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }

  vector<int> diameter=getDiameter();
  int D=diameter.size();

  if(D%3){
    int st=diameter[D/2];
    vector<int> dist=getdist(st,st);

    string ans="";
    rep(i,N){
      dist[i]%=3;
      if(dist[i]==0) ans+='R';
      else if(dist[i]==1) ans+='G';
      else ans+='B';
    }
    cout<<D/3+1<<"\n";
    cout<<ans<<"\n";
    return 0;
  }

  if(D%2==0){
    int st=diameter[D/2-1];
    int ed=diameter[D/2];
    vector<int> dist(N,MOD);
    dist[st]=0;dist[ed]=2;
    queue<int> Q;
    Q.push(st);
    while(!Q.empty()){
        int now=Q.front();
        Q.pop();
        for(auto nex:g[now]){
            if(dist[nex]==MOD){
                dist[nex]=dist[now]+1;
                dist[nex]%=3;
                Q.push(nex);
            }
        }
    }
    Q.push(ed);
    while(!Q.empty()){
        int now=Q.front();
        Q.pop();
        for(auto nex:g[now]){
            if(dist[nex]==MOD){
                dist[nex]=dist[now]-1;
                dist[nex]+=3;
                dist[nex]%=3;
                Q.push(nex);
            }
        }
    }

    string ans="";
    rep(i,N){
      dist[i]%=3;
      if(dist[i]==0) ans+='R';
      else if(dist[i]==1) ans+='G';
      else ans+='B';
    }
    cout<<D/3<<"\n";
    cout<<ans<<"\n";
    return 0;
  }

  {
    int st=diameter[D/2];
    vector<int> dist=getdist(st,st);
    int ma=*max_element(all(dist));

    int masubg=0;
    for(auto nex:g[st]){
        if(dfs(nex,st,1,ma)) masubg++;
    }

    if(masubg>2){
        cout<<D/3+1<<"\n";

        st=diameter[D/2];
        dist=getdist(st,st);

        string ans="";
        rep(i,N){
            dist[i]%=3;
            if(dist[i]==0) ans+='R';
            else if(dist[i]==1) ans+='G';
            else ans+='B';
        }
        cout<<ans<<"\n";
        return 0;
    }else{
        cout<<D/3<<"\n";

        st=diameter[D/2];
        int fir=diameter[D/2-1];
        int sec=diameter[D/2+1];
        vector<int> dist(N,MOD);
        queue<int> Q;
        Q.push(st);Q.push(fir);
        dist[st]=0;dist[fir]=1;
        dist[sec]=2;
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            for(auto nex:g[now]){
                if(dist[nex]==MOD){
                    dist[nex]=dist[now]+1;
                    dist[nex]%=3;
                    Q.push(nex);
                }
            }
        }

        Q.push(sec);
        dist[sec]=2;
        while(!Q.empty()){
            int now=Q.front();
            Q.pop();
            for(auto nex:g[now]){
                if(dist[nex]==MOD){
                    dist[nex]=dist[now]-1;
                    dist[nex]+=3;
                    dist[nex]%=3;
                    Q.push(nex);
                }
            }
        }

        string ans="";
        rep(i,N){
            dist[i]%=3;
            if(dist[i]==0) ans+='R';
            else if(dist[i]==1) ans+='G';
            else ans+='B';
        }
        cout<<ans<<"\n";
    }
    return 0;
  }

  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 28416
final_rank: 3

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T>void debug(vector<vector<T>>&v,ll h,ll w){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout spa v[i][j];cout<<endl;}};
void debug(vector<string>&v,ll h,ll w){for(ll i=0;i<h;i++){for(ll j=0;j<w;j++)cout<<v[i][j];cout<<endl;}};
template<typename T>void debug(vector<T>&v,ll n){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout spa v[i];cout<<endl;};
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
struct edge{
  ll to=-1,cost=0;
  edge(){};
  edge(ll t,ll c):to(t),cost(c){};
};
struct HLD{
  ll n, root;
  ll cnt = 0;
  vector<ll>sz;//部分木サイズ
  vector<ll>par,head;
  vector<vector<struct edge>>g;//隣接リスト
  vector<struct edge>edges;//データ構造に乗せるedge列
  vector<ll>in,out;//[in,out)で部分木、[ina,inb]でa~bのパス(aが上)
  //inは頂点のindexを表す。また、edge列の下側の頂点である
  HLD(vector<vector<struct edge>>&G,ll r = -1)
      :g(G),n(G.size()),root(r){
    par.assign(n,-1),in.assign(n,-1);
    out.assign(n,-1),head.assign(n,-1),sz.assign(n,-1);
    edges.assign(n,edge());
    dfs_build();
  }
  void dfs_build(){
    if(root == -1){//根がどこでも良い場合(森でも可)
      for(ll i=0;i<n;i++){
        if(sz[i] == -1){
          head[i] = i;
          dfs_sz(i);
          dfs_hld(i);
        }
      }
    }
    else{
      head[root] = root;
      dfs_sz(root);
      dfs_hld(root);
    }
  }
  void dfs_sz(ll k){
    sz[k] = 1;
    for(auto &e: g[k]){
      if(e.to == par[k])continue;
      par[e.to] = k;
      dfs_sz(e.to);
      sz[k] += sz[e.to];
      if(sz[e.to] > sz[g[k][0].to])swap(e, g[k][0]);
    }
  }
  void dfs_hld(ll k){
    in[k] = cnt++;
    for(auto e:g[k]){
      if(e.to == par[k])continue;
      head[e.to] = (e.to == g[k][0].to ? head[k]: e.to);
      edges[cnt] = e;
      dfs_hld(e.to);
    }
    out[k] = cnt;
  }
  ll lca(ll p,ll q){
    while(1){
      if(in[p] < in[q])swap(p,q);
      if(head[p] == head[q])return q;
      p = par[head[p]];
    }
  }
  vector<pair<ll,ll>>query_path(ll p,ll q,bool isEdge=true){
    ll r=lca(p,q);
    vector<pair<ll,ll>>ret;
    for(ll i=0;i<2;i++){
      if(i == 1)swap(p,q);
      while(1){
        if(isEdge&&p==r)break;
        if(head[p]==head[r]){
          ret.emplace_back(in[r]+(isEdge?1:i),in[p]+1);
          break;
        }
        ret.emplace_back(in[head[p]],in[p]+1);
        p = par[head[p]];
      }
    }
    return ret;
  }
  vector<vector<pair<ll,ll>>>query_order_path(ll p,ll q,bool isEdge=true){
	//非可換クエリ用、配列0を順番を反転したデータ構造に、配列1を通常のデータ構造に
    vector<vector<pair<ll,ll>>>ret(2);
    ll r=lca(p,q);
    for(ll i=0;i<2;i++){
      if(i == 1)swap(p,q);
      while(1){
        if(isEdge&&p==r)break;
        if(head[p]==head[r]){
          if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[r]+(isEdge?1:i)));
          else ret[i].emplace_back(in[r]+(isEdge?1:i),in[p]+1);
          break;
        }
        if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[head[p]]));
        else ret[i].emplace_back(in[head[p]],in[p]+1);
        p = par[head[p]];
      }
    }
    reverse(ret[1].begin(), ret[1].end());
    return ret;
  }
  pair<ll,ll>query_subtree(ll p,bool isEdge=true){
    return make_pair(in[p]+isEdge,out[p]);
  }
};
template<typename T>
struct BIT{
  ll n;
  ll k=1;
  vector<T>data;
  BIT() = default;
  BIT(ll size):n(size){
    data.assign(n,0);
    while(k*2<=n)k*=2;
  }
  void add(ll a,T w){
    for(ll i=a+1;i<=n;i+=i&-i)data[i-1]+=w;
  }
  T sum(ll a){
	if(a<0)return 0;
    T ret = 0;
    for(ll i=a+1;i>0;i-=i&-i)ret+=data[i-1];
    return ret;
  }
  T sum(ll a,ll b){return a>b?0:sum(b)-sum(a-1);}
  T operator[](ll pos){
    return sum(pos,pos);
  }
  ll lower_bound(ll x){
    ll ret=0;    
    for(ll i=k;i>0;i/=2){
      if(ret+i<=n&&data[ret+i-1]<x){
        x-=data[ret+i-1];
        ret+=i;
      }
    }
    return ret;
  }
  void print(){
    for(ll i=0;i<n;i++){
      if(i!=0)cout<<" ";
      cout<<(*this)[i];
    }
    cout<<endl;
  }
};
struct Diameter{
  vector<ll>dep,ret;
  ll n;
  vector<vector<ll>>g;
  ll diam,root,end;
  Diameter(vector<vector<ll>>&G):g(G),n(G.size()){
    dep.assign(n,-1LL);
    dfs(0,0);
    root = max_element(ALL(dep)) - dep.begin();
    fill(ALL(dep),-1LL);
    dfs(root,0);
    end = max_element(ALL(dep)) - dep.begin();
    diam = dep[end];
  }
  void dfs(ll k, ll d){
    dep[k] = d;
    for(auto to:g[k]){
      if(dep[to]==-1)dfs(to,d+1);
    }
  }
  vector<ll>diam_path(){
    vector<ll>tmp;
    dfs2(root,-1,tmp);
    return ret;
  }
  void dfs2(ll k, ll par,vector<ll>&v){
    v.PB(k);
    if(k==end)ret=v;
    for(auto to:g[k]){
      if(par!=to)dfs2(to,k,v);
    }
    v.pop_back();
  }
};
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n;cin>>n;
  vector<vector<edge>>g(n);
  vector<vector<ll>>gw(n);
  rep(i,0,n-1){
    ll u,v;cin>>u>>v;u--;v--;
    g[u].EB(v,1);
    g[v].EB(u,1);
    gw[u].PB(v);
    gw[v].PB(u);
  }
  HLD hld(g);
  Diameter dia(gw);
  string s(n,'?');
  string r="RGB";
  vector<BIT<ll>>bit(3,BIT<ll>(n));
  auto vd=dia.diam_path();
  vector<ll>td(n,-1);
  rep(i,0,vd.size()){
    if(i*2<vd.size())td[vd[i]]=0;
    else td[vd[i]]=1;
  }
  //debug(td,n);
  //debug(vd,vd.size());
  {

    auto dfs=[&](auto &&f,ll k,ll par,ll d,ll flip)->void{
      s[k]=r[d];
      bit[d].add(hld.in[k],1);
      for(auto to:gw[k]){
        if(to==par)continue;
        if(flip||(td[k]==0&&td[to]==-1))f(f,to,k,(d+2)%3,1);
        else f(f,to,k,(d+1)%3,0);
      }
    };
    dfs(dfs,dia.root,-1,0,0);
  }
  //cout<<dia.root spa dia.end spa dia.diam<<endl;
  rep(i,0,n){
    for(auto to:{dia.root,dia.end}){
    //for(auto to:v){
      auto p=hld.query_path(i,to,false);
      rep(j,0,3){
        ll now=0;
        for(auto z:p)now+=bit[j].sum(z.fi,z.se-1);
        chmax(res,now);
      }
    }
  }
  cout<<res<<endl;
  cout<<s<<endl;
  return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 88128
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
const int N=200000;
vector<int> g[N];
int res[N];

void paint_tree(int s,int p,int c,int sn){
	res[s]=c;
	for(int t:g[s]){
		if(t==p)continue;
		paint_tree(t,s,(c+sn+3)%3,sn);
	}
}

void printres(int n){
	for(int i=0;i<n;i++){
		if(res[i]==0)printf("R");
		if(res[i]==1)printf("G");
		if(res[i]==2)printf("B");
	}
	printf("\n");
}

int main(){
	int n; cin >> n;
	for(int i=1;i<n;i++){
		int x,y; cin >> x >> y;
		x--; y--;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	queue<int> q;
	q.push(0);
	vector<int> d(n);
	while(q.size()){
		int s=q.front(); q.pop();
		for(int t:g[s]){
			if(t!=0&&d[t]==0){
				d[t]=d[s]+1;
				q.push(t);
			}
		}
	}
	int id=-1;
	int mx=-1;
	for(int i=0;i<n;i++){
		if(mx<d[i]){
			mx=d[i];
			id=i;
		}
	}
	vector<int> dd(n);
	q.push(id);
	while(q.size()){
		int s=q.front(); q.pop();
		for(int t:g[s]){
			if(t!=id&&dd[t]==0){
				dd[t]=dd[s]+1;
				q.push(t);
			}
		}
	}
	int D=*max_element(dd.begin(), dd.end());
	D++;
	if(D%3){
		printf("%d\n",(D+2)/3);
		paint_tree(0,-1,0,1);
		printres(n);
	}
	else{
		if(D%2==0){
			int jd=-1;
			for(int i=0;i<n;i++){
				if(dd[i]==D-1)jd=i;
			}
			vector<int> ddd(n);
			q.push(jd);
			while(q.size()){
				int s=q.front(); q.pop();
				for(int t:g[s]){
					if(t!=jd&&ddd[t]==0){
						ddd[t]=ddd[s]+1;
						q.push(t);
					}
				}
			}
			for(int i=0;i<n;i++){
				if(dd[i]==D/2-1&&ddd[i]==D/2)id=i;
				if(dd[i]==D/2&&ddd[i]==D/2-1)jd=i;
			}
			printf("%d\n",D/3);
			paint_tree(id,jd,0,1);
			paint_tree(jd,id,2,-1);
			printres(n);
		}
		else{
			int jd=-1;
			for(int i=0;i<n;i++){
				if(dd[i]==D-1)jd=i;
			}
			vector<int> ddd(n);
			q.push(jd);
			while(q.size()){
				int s=q.front(); q.pop();
				for(int t:g[s]){
					if(t!=jd&&ddd[t]==0){
						ddd[t]=ddd[s]+1;
						q.push(t);
					}
				}
			}
			for(int i=0;i<n;i++){
				if(dd[i]==D/2&&ddd[i]==D/2)id=i;
				d[i]=0;
			}
			q.push(id);
			while(q.size()){
				int s=q.front(); q.pop();
				for(int t:g[s]){
					if(t!=id&&d[t]==0){
						d[t]=d[s]+1;
						q.push(t);
					}
				}
			}
			int cnt=0;
			int DD=*max_element(d.begin(), d.end());
			vector<bool>used(n);
			used[id]=1;
			for(int s:g[id]){
				bool ok=0;
				queue<int> qq;
				qq.push(s);
				while(qq.size()){
					int ss=qq.front(); qq.pop();
					if(d[ss]==DD)ok=1;
					used[ss]=1;
					for(int t:g[ss]){
						if(!used[t])qq.push(t);
					}
				}
				if(ok)cnt++;
			}
			if(cnt>=3){
				printf("%d\n",(D+3)/3);
				paint_tree(0,-1,0,1);
				printres(n);
			}
			else{
				int kd=-1;
				for(int i=0;i<n;i++){
					if(d[i]==1&&ddd[i]+1==ddd[id])kd=i;
				}
				printf("%d\n",D/3);
				paint_tree(id,kd,0,1);
				paint_tree(kd,id,2,-1);
				printres(n);
			}
		}
	}
}
accuracy: 1
time_ms: 140
memory_kb: 28860
final_rank: 6

code_snippet: #pragma region Macros
#pragma GCC optimize("O3")
#pragma GCC target("avx2,avx")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
string YES[2] = {"NO", "YES"};
string Yes[2] = {"No", "Yes"};
string yes[2] = {"no", "yes"};
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto &e : v) cout << e << " ";
    cout << endl;
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    cout << "(" << p.fi << ", " << p.se << ")";
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
template <class A> string to_string(A v) {
    if(v.empty()) return "{}";
    string ret = "{";
    for(auto &x : v) ret += to_string(x) + ",";
    ret.back() = '}';
    return ret;
}

void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
#define debug(x)
#endif
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
// ll rndll(ll n) { return uniform_int_distribution<ll>(0, n - 1)(rng); }

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#pragma endregion

using tree = Graph;
int search_center(tree &g) {
    vector<int> res;
    int max_depth = -1, leaf;
    auto dfs = [&](auto &&self, int x, int p, int d, bool looking = false) -> bool {
        bool flag = false;
        if(max_depth < d) {
            max_depth = d, leaf = x, flag = true;
            res.clear();
        }
        for(auto e : g[x]) {
            if(e != p) flag |= self(self, e, x, d + 1, looking);
        }
        if(looking and flag and d == (max_depth >> 1) or d == ((max_depth + 1) >> 1)) res.emplace_back(x);
        return flag;
    };
    dfs(dfs, 0, -1, 0);
    max_depth = -1;
    dfs(dfs, leaf, -1, 0, true);
    return res[0];
}
int main() {
    string s = "RGB";
    INT(n);
    Graph g = getG(n);
    if(n <= 3) {
        cout << 1 << endl;
        cout << s.substr(0, n) << endl;
        exit(0);
    }
    vi ans(n);
    int num = 0;
    int c = search_center(g);
    vi d(n);
    {
        auto dfs = [&](auto &&f, int x, int p) -> int {
            d[x] = 1;
            for(auto e : g[x])
                if(e != p) chmax(d[x], f(f, e, x) + 1);
            return d[x];
        };
        dfs(dfs, c, -1);
    }
    int ma[2] = {};
    vi v;
    for(auto e : g[c]) v.eb(d[e]);
    sort(all(v), greater<>());
    num = 1 + v[0] / 3 + v[1] / 3;
    int cnt = 0;
    for(auto e : v)
        if(v[0] / 3 == e / 3) cnt += e % 3;
    if(cnt > 2) num++;
    cout << num << endl;
    auto dfs = [&](auto &&f, int x, int p, int col, int dx) -> void {
        ans[x] = col;
        col = (col + 3 + dx) % 3;
        for(auto e : g[x])
            if(e != p) f(f, e, x, col, dx);
    };
    vi w;
    for(auto e : g[c]) w.eb(e);
    sort(all(w), [&](int i, int j) { return d[i] > d[j]; });
    int k = 1;
    for(auto e : w) {
        dfs(dfs, e, c, (3 + k) % 3, k);
        k *= -1;
    }
    rep(i, n) cout << s[ans[i]];
    cout << endl;
}
accuracy: 1
time_ms: 70
memory_kb: 34304
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef int_fast32_t int32;
typedef int_fast64_t int64;

const int32 inf = 1e9+7;
const int32 MOD = 1000000007;
const int64 llinf = 1e18;

#define YES(n) cout << ((n) ? "YES\n" : "NO\n"  )
#define Yes(n) cout << ((n) ? "Yes\n" : "No\n"  )
#define POSSIBLE(n) cout << ((n) ? "POSSIBLE\n" : "IMPOSSIBLE\n"  )
#define ANS(n) cout << (n) << "\n"
#define REP(i,n) for(int64 i=0;i<(n);++i)
#define FOR(i,a,b) for(int64 i=(a);i<(b);i++)
#define FORR(i,a,b) for(int64 i=(a);i>=(b);i--)
#define all(obj) (obj).begin(),(obj).end()
#define rall(obj) (obj).rbegin(),(obj).rend()
#define fi first
#define se second
#define pb(a) push_back(a)
typedef pair<int32,int32> pii;
typedef pair<int64,int64> pll;

template<class T> inline bool chmax(T& a, T b) {
    if (a < b) { a = b; return true; } return false;
}
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) { a = b; return true; } return false;
}

vector<vector<int32>> adj;
vector<int32> dist;

void dfs(int32 v){
    for(auto u : adj[v]){
        if(dist[u] != inf)continue;
        dist[u] = dist[v] + 1;
        dfs(u);
    }
}


vector<int32> mxdepth;

int32 dfs2(int32 v, int32 p = -1){
    for(auto u : adj[v]){
        if(u == p)continue;
        chmax(mxdepth[v],dfs2(u,v));
    }
    return mxdepth[v];
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int32 n;
    cin >> n;
    adj.resize(n);
    REP(i,n-1){
        int32 a,b;
        cin >> a >> b;
        --a;--b;
        adj[a].pb(b);
        adj[b].pb(a);
    }

    dist.resize(n,inf);
    dist[0] = 0;
    dfs(0);
    // REP(i,n)ANS(dist[i]);
    int32 s = -1;
    {
        int32 mx = 0;
        REP(i,n)chmax(mx, dist[i]);
        REP(i,n){
            if(dist[i] == mx){
                s = i;
                break;
            }
        }
    }

    dist = vector<int32>(n,inf);
    dist[s] = 0;
    dfs(s);
    int32 t = -1;
    {
        int32 mx = 0;
        REP(i,n)chmax(mx, dist[i]);
        REP(i,n){
            if(dist[i] == mx){
                t = i;
                break;
            }
        }
    }
    // ANS(s);
    // ANS(t);
    int32 diam = dist[t];
    // ANS(diam);

    vector<int32> diampath;
    int32 cur = t;
    diampath.pb(t);
    while(cur != s){
        for(auto v : adj[cur]){
            if(dist[v] == dist[cur] - 1){
                diampath.pb(v);
                cur = v;
            }
        }
    }
    // for(auto v : diampath){
    //     ANS(v+1);
    // }

    dist = vector<int32>(n,inf);
    dist[diampath[diam/2]] = 0;
    dfs(diampath[diam/2]);
    vector<int32> depth1 = dist;

    dist = vector<int32>(n,inf);
    dist[diampath[diam/2+1]] = 0;
    dfs(diampath[diam/2+1]);
    vector<int32> depth2 = dist;

    vector<int32> color(n,-1);
    REP(i,n){
        if(depth1[i] < depth2[i]){
            color[i] = depth1[i] % 3;
        }else{
            color[i] = 2 - depth2[i] % 3;
        }
    }

    mxdepth = depth1;
    dfs2(diampath[diam/2]);
    int32 cnt = 0;
    for(auto v : adj[diampath[diam/2]]){
        if(mxdepth[v] == diam/2)++cnt;
    }

    if(diam % 6 == 2 && cnt >= 3){
        ANS((diam+3)/3+1);
    }else{
        ANS((diam+3)/3);
    }

    REP(i,n){
        // ANS(color[i]);
        if(color[i] == 0){
            cout << "R";
        }else if(color[i] == 1){
            cout << "G";
        }else{
            cout << "B";
        }
    }
    cout << endl;
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 29568
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef int_fast32_t int32;
typedef int_fast64_t int64;

const int32 inf = 1e9+7;
const int32 MOD = 1000000007;
const int64 llinf = 1e18;

#define YES(n) cout << ((n) ? "YES\n" : "NO\n"  )
#define Yes(n) cout << ((n) ? "Yes\n" : "No\n"  )
#define POSSIBLE(n) cout << ((n) ? "POSSIBLE\n" : "IMPOSSIBLE\n"  )
#define ANS(n) cout << (n) << "\n"
#define REP(i,n) for(int64 i=0;i<(n);++i)
#define FOR(i,a,b) for(int64 i=(a);i<(b);i++)
#define FORR(i,a,b) for(int64 i=(a);i>=(b);i--)
#define all(obj) (obj).begin(),(obj).end()
#define rall(obj) (obj).rbegin(),(obj).rend()
#define fi first
#define se second
#define pb(a) push_back(a)
typedef pair<int32,int32> pii;
typedef pair<int64,int64> pll;

template<class T> inline bool chmax(T& a, T b) {
    if (a < b) { a = b; return true; } return false;
}
template<class T> inline bool chmin(T& a, T b) {
    if (a > b) { a = b; return true; } return false;
}

vector<vector<int32>> adj;
vector<int32> dist;

void dfs(int32 v){
    for(auto u : adj[v]){
        if(dist[u] != inf)continue;
        dist[u] = dist[v] + 1;
        dfs(u);
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int32 n;
    cin >> n;
    adj.resize(n);
    REP(i,n-1){
        int32 a,b;
        cin >> a >> b;
        --a;--b;
        adj[a].pb(b);
        adj[b].pb(a);
    }

    dist.resize(n,inf);
    dist[0] = 0;
    dfs(0);
    // REP(i,n)ANS(dist[i]);
    int32 s = -1;
    {
        int32 mx = 0;
        REP(i,n)chmax(mx, dist[i]);
        REP(i,n){
            if(dist[i] == mx){
                s = i;
                break;
            }
        }
    }

    dist = vector<int32>(n,inf);
    dist[s] = 0;
    dfs(s);
    int32 t = -1;
    {
        int32 mx = 0;
        REP(i,n)chmax(mx, dist[i]);
        REP(i,n){
            if(dist[i] == mx){
                t = i;
                break;
            }
        }
    }
    // ANS(s);
    // ANS(t);
    int32 diam = dist[t];
    // ANS(diam);

    vector<int32> diampath;
    int32 cur = t;
    diampath.pb(t);
    while(cur != s){
        for(auto v : adj[cur]){
            if(dist[v] == dist[cur] - 1){
                diampath.pb(v);
                cur = v;
            }
        }
    }
    // for(auto v : diampath){
    //     ANS(v+1);
    // }

    dist = vector<int32>(n,inf);
    dist[diampath[diam/2]] = 0;
    dfs(diampath[diam/2]);
    vector<int32> depth1 = dist;

    dist = vector<int32>(n,inf);
    dist[diampath[diam/2+1]] = 0;
    dfs(diampath[diam/2+1]);
    vector<int32> depth2 = dist;

    vector<int32> color(n,-1);
    REP(i,n){
        if(depth1[i] < depth2[i]){
            color[i] = depth1[i] % 3;
        }else{
            color[i] = 2 - depth2[i] % 3;
        }
    }

    if(diam == 2 && n >= 4){
        ANS(2);
    }else{
        ANS((diam+3)/3);        
    }

    REP(i,n){
        // ANS(color[i]);
        if(color[i] == 0){
            cout << "R";
        }else if(color[i] == 1){
            cout << "G";
        }else{
            cout << "B";
        }
    }
    cout << endl;
    return 0;
}
accuracy: 0.9444444444444444
time_ms: 80
memory_kb: 27852
final_rank: 18

code_snippet: #pragma region kyopro_template
#define Nyaan_template
#include <immintrin.h>
#include <bits/stdc++.h>
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define each(x, v) for (auto &x : v)
#define all(v) (v).begin(), (v).end()
#define sz(v) ((int)(v).size())
#define mem(a, val) memset(a, val, sizeof(a))
#define ini(...)   \
  int __VA_ARGS__; \
  in(__VA_ARGS__)
#define inl(...)         \
  long long __VA_ARGS__; \
  in(__VA_ARGS__)
#define ins(...)      \
  string __VA_ARGS__; \
  in(__VA_ARGS__)
#define inc(...)    \
  char __VA_ARGS__; \
  in(__VA_ARGS__)
#define in2(s, t)                           \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i]);                         \
  }
#define in3(s, t, u)                        \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i]);                   \
  }
#define in4(s, t, u, v)                     \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i], v[i]);             \
  }
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define die(...)      \
  do {                \
    out(__VA_ARGS__); \
    return;           \
  } while (0)
using namespace std;
using ll = long long;
template <class T>
using V = vector<T>;
using vi = vector<int>;
using vl = vector<long long>;
using vvi = vector<vector<int>>;
using vd = V<double>;
using vs = V<string>;
using vvl = vector<vector<long long>>;
using P = pair<long long, long long>;
using vp = vector<P>;
using pii = pair<int, int>;
using vpi = vector<pair<int, int>>;
constexpr int inf = 1001001001;
constexpr long long infLL = (1LL << 61) - 1;
template <typename T, typename U>
inline bool amin(T &x, U y) {
  return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
  return (x < y) ? (x = y, true) : false;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}
void in() {}
template <typename T, class... U>
void in(T &t, U &... u) {
  cin >> t;
  in(u...);
}
void out() { cout << "\n"; }
template <typename T, class... U>
void out(const T &t, const U &... u) {
  cout << t;
  if (sizeof...(u)) cout << " ";
  out(u...);
}

#ifdef NyaanDebug
#define trc(...)                   \
  do {                             \
    cerr << #__VA_ARGS__ << " = "; \
    dbg_out(__VA_ARGS__);          \
  } while (0)
#define trca(v, N)       \
  do {                   \
    cerr << #v << " = "; \
    array_out(v, N);     \
  } while (0)
#define trcc(v)                             \
  do {                                      \
    cerr << #v << " = {";                   \
    each(x, v) { cerr << " " << x << ","; } \
    cerr << "}" << endl;                    \
  } while (0)
template <typename T>
void _cout(const T &c) {
  cerr << c;
}
void _cout(const int &c) {
  if (c == 1001001001)
    cerr << "inf";
  else if (c == -1001001001)
    cerr << "-inf";
  else
    cerr << c;
}
void _cout(const unsigned int &c) {
  if (c == 1001001001)
    cerr << "inf";
  else
    cerr << c;
}
void _cout(const long long &c) {
  if (c == 1001001001 || c == (1LL << 61) - 1)
    cerr << "inf";
  else if (c == -1001001001 || c == -((1LL << 61) - 1))
    cerr << "-inf";
  else
    cerr << c;
}
void _cout(const unsigned long long &c) {
  if (c == 1001001001 || c == (1LL << 61) - 1)
    cerr << "inf";
  else
    cerr << c;
}
template <typename T, typename U>
void _cout(const pair<T, U> &p) {
  cerr << "{ ";
  _cout(p.fi);
  cerr << ", ";
  _cout(p.se);
  cerr << " } ";
}
template <typename T>
void _cout(const vector<T> &v) {
  int s = v.size();
  cerr << "{ ";
  for (int i = 0; i < s; i++) {
    cerr << (i ? ", " : "");
    _cout(v[i]);
  }
  cerr << " } ";
}
template <typename T>
void _cout(const vector<vector<T>> &v) {
  cerr << "[ ";
  for (const auto &x : v) {
    cerr << endl;
    _cout(x);
    cerr << ", ";
  }
  cerr << endl << " ] ";
}
void dbg_out() { cerr << endl; }
template <typename T, class... U>
void dbg_out(const T &t, const U &... u) {
  _cout(t);
  if (sizeof...(u)) cerr << ", ";
  dbg_out(u...);
}
template <typename T>
void array_out(const T &v, int s) {
  cerr << "{ ";
  for (int i = 0; i < s; i++) {
    cerr << (i ? ", " : "");
    _cout(v[i]);
  }
  cerr << " } " << endl;
}
template <typename T>
void array_out(const T &v, int H, int W) {
  cerr << "[ ";
  for (int i = 0; i < H; i++) {
    cerr << (i ? ", " : "");
    array_out(v[i], W);
  }
  cerr << " ] " << endl;
}
#else
#define trc(...)
#define trca(...)
#define trcc(...)
#endif

inline int popcnt(unsigned long long a) { return __builtin_popcountll(a); }
inline int lsb(unsigned long long a) { return __builtin_ctzll(a); }
inline int msb(unsigned long long a) { return 63 - __builtin_clzll(a); }
template <typename T>
inline int getbit(T a, int i) {
  return (a >> i) & 1;
}
template <typename T>
inline void setbit(T &a, int i) {
  a |= (1LL << i);
}
template <typename T>
inline void delbit(T &a, int i) {
  a &= ~(1LL << i);
}
template <typename T>
int lb(const vector<T> &v, const T &a) {
  return lower_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int ub(const vector<T> &v, const T &a) {
  return upper_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int btw(T a, T x, T b) {
  return a <= x && x < b;
}
template <typename T, typename U>
T ceil(T a, U b) {
  return (a + b - 1) / b;
}
constexpr long long TEN(int n) {
  long long ret = 1, x = 10;
  while (n) {
    if (n & 1) ret *= x;
    x *= x;
    n >>= 1;
  }
  return ret;
}
template <typename T>
vector<T> mkrui(const vector<T> &v) {
  vector<T> ret(v.size() + 1);
  for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i];
  return ret;
};
template <typename T>
vector<T> mkuni(const vector<T> &v) {
  vector<T> ret(v);
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}
template <typename F>
vector<int> mkord(int N, F f) {
  vector<int> ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), f);
  return ord;
}
template <typename T = int>
vector<T> mkiota(int N) {
  vector<T> ret(N);
  iota(begin(ret), end(ret), 0);
  return ret;
}
template <typename T>
vector<int> mkinv(vector<T> &v) {
  vector<int> inv(v.size());
  for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i;
  return inv;
}

struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(7);
  }
} iosetupnya;

void solve();
int main() { solve(); }

#pragma endregion
using namespace std;

template <typename T>
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnweightedGraph = vector<vector<int>>;

// Input of (Unweighted) Graph
UnweightedGraph graph(int N, int M = -1, bool is_directed = false,
                      bool is_1origin = true) {
  UnweightedGraph g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    if (is_1origin) x--, y--;
    g[x].push_back(y);
    if (!is_directed) g[y].push_back(x);
  }
  return g;
}

// Input of Weighted Graph
template <typename T>
WeightedGraph<T> wgraph(int N, int M = -1, bool is_directed = false,
                        bool is_1origin = true) {
  WeightedGraph<T> g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    cin >> c;
    if (is_1origin) x--, y--;
    g[x].eb(x, y, c);
    if (!is_directed) g[y].eb(y, x, c);
  }
  return g;
}

// Input of Edges
template <typename T>
Edges<T> esgraph(int N, int M, int is_weighted = true, bool is_1origin = true) {
  Edges<T> es;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    es.emplace_back(x, y, c);
  }
  return es;
}

// Input of Adjacency Matrix
template <typename T>
vector<vector<T>> adjgraph(int N, int M, T INF, int is_weighted = true,
                           bool is_directed = false, bool is_1origin = true) {
  vector<vector<T>> d(N, vector<T>(N, INF));
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    d[x][y] = c;
    if (!is_directed) d[y][x] = c;
  }
  return d;
}
using namespace std;


// Depth of Rooted Tree
// unvisited nodes : d = -1
vector<int> Depth(const UnweightedGraph &g, int start = 0) {
  vector<int> d(g.size(), -1);
  auto dfs = [&](auto rec, int cur, int par = -1) -> void {
    d[cur] = par == -1 ? 0 : d[par] + 1;
    for (auto &dst : g[cur]) {
      if (dst == par) continue;
      rec(rec, dst, cur);
    }
  };
  dfs(dfs, start);
  return d;
}

// Depth of Rooted Weighted Tree
// unvisited nodes : d = -1
template <typename T>
vector<T> Depth(const WeightedGraph<T> &g, int start = 0) {
  vector<T> d(g.size(), -1);
  auto dfs = [&](auto rec, int cur, T val, int par = -1) -> void {
    d[cur] = val;
    for (auto &dst : g[cur]) {
      if (dst == par) continue;
      rec(rec, dst, val + dst.cost, cur);
    }
  };
  dfs(dfs, start, 0);
  return d;
}

// Diameter of Tree
// return value : { {u, v}, length }
pair<pair<int, int>, int> Diameter(const UnweightedGraph &g) {
  auto d = Depth(g, 0);
  int u = max_element(begin(d), end(d)) - begin(d);
  d = Depth(g, u);
  int v = max_element(begin(d), end(d)) - begin(d);
  return make_pair(make_pair(u, v), d[v]);
}

// Diameter of Weighted Tree
// return value : { {u, v}, length }
template <typename T>
pair<pair<int, int>, T> Diameter(const WeightedGraph<T> &g) {
  auto d = Depth(g, 0);
  int u = max_element(begin(d), end(d)) - begin(d);
  d = Depth(g, u);
  int v = max_element(begin(d), end(d)) - begin(d);
  return make_pair(make_pair(u, v), d[v]);
}

// nodes on the path u-v ( O(N) )
template <typename G>
vector<int> Path(G &g, int u, int v) {
  vi ret;
  int end = 0;
  auto dfs = [&](auto rec, int cur, int par = -1) -> void {
    ret.push_back(cur);
    if (cur == v) {
      end = 1;
      return;
    }
    for (int dst : g[cur]) {
      if (dst == par) continue;
      rec(rec, dst, cur);
      if (end) return;
    }
    if (end) return;
    ret.pop_back();
  };
  dfs(dfs, u);
  return ret;
}

string ans;
int n = 0;

template <typename G>
struct CentroidDecomposition {
  const G &g;
  vector<int> sub;
  vector<bool> v;
  vector<vector<int>> tree;
  int root;

  CentroidDecomposition(const G &g_, int isbuild = true) : g(g_) {
    sub.resize(g.size(), 0);
    v.resize(g.size(), false);
    if (isbuild) build();
  }

  void build() {
    tree.resize(g.size());
    root = build_dfs(0);
  }

  int get_size(int cur, int par) {
    sub[cur] = 1;
    for (auto &dst : g[cur]) {
      if (dst == par || v[dst]) continue;
      sub[cur] += get_size(dst, cur);
    }
    return sub[cur];
  }

  int get_centroid(int cur, int par, int mid) {
    for (auto &dst : g[cur]) {
      if (dst == par || v[dst]) continue;
      if (sub[dst] > mid) return get_centroid(dst, cur, mid);
    }
    return cur;
  }

  array<int, 3> calc(int cur, int par) {
    array<int, 3> r1{0, 0, 0}, r2{0, 0, 0};
    for (auto &dst : g[cur]) {
      if (dst == par || v[dst]) continue;
      auto d = calc(dst, cur);
      rep(i, 3) {
        if (d[i] > r1[i]) swap(d[i], r1[i]);
        if (d[i] > r2[i]) swap(d[i], r2[i]);
      }
    }
    if (ans[cur] == 'R') r1[0]++;
    if (ans[cur] == 'G') r1[1]++;
    if (ans[cur] == 'B') r1[2]++;
    rep(i, 3) amax(n, r1[i] + r2[i]);
    return r1;
  }

  int build_dfs(int cur) {
    int centroid = get_centroid(cur, -1, get_size(cur, -1) / 2);
    v[centroid] = true;
    calc(centroid, -1);
    for (auto &dst : g[centroid]) {
      if (!v[dst]) {
        int nxt = build_dfs(dst);
        if (centroid != nxt) tree[centroid].emplace_back(nxt);
      }
    }
    v[centroid] = false;
    return centroid;
  }
};

int solve_(int N, vvi g) {
  // ini(N);
  // auto g = graph(N);
  ans.resize(N);
  fill(all(ans), ' ');

  auto [p, l] = Diameter(g);
  auto [u, v] = p;
  auto path = Path(g, u, v);

  int i = 0;
  auto c = [&]() { return i == 0 ? 'R' : i == 1 ? 'G' : 'B'; };
  //int i = 0;
  rep(j,sz(path)) {
    ans[path[j]] = c();
    i = (i + 1) % 3;
  } 
  //out(path);
  //out(ans);
  {
    i = 0;
    int rev = 0;
    auto dfs = [&](auto rec, int cur, int par) -> void {
      ans[cur] = c();
      each(dst, g[cur]) {
        if (dst == par || ans[dst] != ' ') continue;
        i = (rev ? (i + 2) % 3 : (i + 1) % 3);
        rec(rec, dst, cur);
        i = (rev ? (i + 1) % 3 : (i + 2) % 3);
      }
    };
    for(int j = 0; j < sz(path); j++){
      if(j * 2 <= sz(path) ) rev = 1;
      else rev = 0;
      i = j % 3;
      dfs(dfs, path[j], -1);
    }
  }
  each(x, ans) if (x == ' ') exit(1);
  // trc(ans);
  n = 0;
  CentroidDecomposition<vvi> dec(g);
  out(n);
  out(ans);
  return n;
}

int naive(int N, vvi g) {
  ans.resize(N, ' ');
  int n2 = inf;
  rep(i, int(pow(3, N))) {
    int j = i;
    rep(_, N) {
      int k = j % 3;
      j /= 3;
      ans[_] = (k == 0 ? 'R' : k == 1 ? 'G' : 'B');
    }
      n = 0;
    CentroidDecomposition<vvi> dec(g);
    amin(n2, n);
  }
  return n2;
}

void solve() {
  /**/
  ini(N);
  auto g=graph(N);
  solve_(N,g);
  //*/
  /**
  mt19937 rng;
  while (1) {
    int N = rng() % 7 + 2;
    vvi g(N);
    rep1(i, N - 1) {
      int j = rng() % i;
      g[i].push_back(j);
      g[j].push_back(i);
    }
    int n1 = solve_(N, g);
    int n2 = naive(N, g);
    if (n1 != n2) {
      trc(N);
      trc(g);
      trc(n1, n2);
      exit(1);
    }
    //trc(N);
  }
  //*/
  
}
accuracy: 1
time_ms: 310
memory_kb: 54372
final_rank: 15

code_snippet: #pragma region Macros
#pragma GCC optimize("O3")
#pragma GCC target("avx2,avx")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
string YES[2] = {"NO", "YES"};
string Yes[2] = {"No", "Yes"};
string yes[2] = {"no", "yes"};
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return move(res);
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return move(res);
}

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto &e : v) cout << e << " ";
    cout << endl;
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    cout << "(" << p.fi << ", " << p.se << ")";
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
template <class A> string to_string(A v) {
    if(v.empty()) return "{}";
    string ret = "{";
    for(auto &x : v) ret += to_string(x) + ",";
    ret.back() = '}';
    return ret;
}

void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#define endl '\n'
#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
#define debug(x)
#endif
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
// ll rndll(ll n) { return uniform_int_distribution<ll>(0, n - 1)(rng); }

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#pragma endregion

using tree = Graph;
int search_center(tree &g) {
    vector<int> res;
    int max_depth = -1, leaf;
    auto dfs = [&](auto &&self, int x, int p, int d, bool looking = false) -> bool {
        bool flag = false;
        if(max_depth < d) {
            max_depth = d, leaf = x, flag = true;
            res.clear();
        }
        for(auto e : g[x]) {
            if(e != p) flag |= self(self, e, x, d + 1, looking);
        }
        if(looking and flag and d == (max_depth >> 1) or d == ((max_depth + 1) >> 1)) res.emplace_back(x);
        return flag;
    };
    dfs(dfs, 0, -1, 0);
    max_depth = -1;
    dfs(dfs, leaf, -1, 0, true);
    return res[0];
}
int main() {
    string s = "RGB";
    INT(n);
    Graph g = getG(n);
    if(n <= 3) {
        cout << 1 << endl;
        cout << s.substr(0, n) << endl;
        exit(0);
    }
    vi ans(n);
    int num = 0;
    int c = search_center(g);
    vi d(n);
    {
        auto dfs = [&](auto &&f, int x, int p) -> int {
            d[x] = 1;
            for(auto e : g[x])
                if(e != p) chmax(d[x], f(f, e, x) + 1);
            return d[x];
        };
        dfs(dfs, c, -1);
    }
    int ma[2] = {};
    vi v;
    for(auto e : g[c]) v.eb(d[e]);
    sort(all(v), greater<>());
    num = 1 + v[0] / 3 + v[1] / 3;
    int cnt = 0;
    for(auto e : v)
        if(v[0] / 3 == e / 3) cnt += e % 3;
    if(cnt > 2) num++;
    cout << num << endl;
    auto dfs = [&](auto &&f, int x, int p, int col, int dx) -> void {
        ans[x] = col;
        col = (col + 3 + dx) % 3;
        for(auto e : g[x])
            if(e != p) f(f, e, x, col, dx);
    };
    vi w;
    for(auto e : g[c]) w.eb(e);
    sort(all(w), [&](int i, int j) { return d[i] > d[j]; });
    int k = 1;
    for(auto e : w) {
        dfs(dfs, e, c, (3 + k) % 3, k);
        k *= -1;
    }
    rep(i, n) cout << s[ans[i]];
    cout << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 34400
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=200005,INF=1<<30;
vector<int> G[MAX];
int deg[MAX];
int ans[MAX];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    
    if(N==1){
        cout<<1<<endl;
        cout<<"R"<<endl;
        return 0;
    }
    
    for(int i=0;i<N-1;i++){
        int a,b;cin>>a>>b;
        a--;b--;
        G[a].push_back(b);
        G[b].push_back(a);
        deg[a]++;
        deg[b]++;
    }
    
    memset(ans,-1,sizeof(ans));
    
    int rem=N,now=0,res=0;
    
    set<int> SE;
    for(int i=0;i<N;i++) if(deg[i]==1) SE.insert(i);
    
    while(rem){
        set<int> nex;
        if(rem<=3&&now%3==0){
            int cnt=0;
            for(int i=0;i<N;i++){
                if(ans[i]==-1){
                    ans[i]=cnt;
                    cnt++;
                }
            }
            res=now/3*2+1;
            
            break;
        }else{
            for(auto a:SE){
                ans[a]=now;
                deg[a]=0;
                rem--;
                
                for(int to:G[a]){
                    if(ans[to]!=-1) continue;
                    deg[to]--;
                    if(deg[to]==1) nex.insert(to);
                }
            }
            
            res=(now/3+1)*2;
        }
        
        now++;
        SE=nex;
    }
    
    cout<<res<<endl;
    
    for(int i=0;i<N;i++){
        if(ans[i]%3==0) cout<<'R';
        else if(ans[i]%3==1) cout<<'G';
        else cout<<'B';
    }
    cout<<endl;
}
accuracy: 1
time_ms: 90
memory_kb: 25276
final_rank: 1

code_snippet: #include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#include<cassert>
#include<random>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (int)(Y);++(X))
#define reps(X,S,Y) for (int (X) = (int)(S);(X) < (int)(Y);++(X))
#define rrep(X,Y) for (int (X) = (int)(Y)-1;(X) >=0;--(X))
#define rreps(X,S,Y) for (int (X) = (int)(Y)-1;(X) >= (int)(S);--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())
#define Endl endl
#define NL <<"\n"
#define cauto const auto

using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
template<class T> using vv=vector<vector<T>>;
template<class T> inline bool MX(T &l,const T &r){return l<r?l=r,1:0;}
template<class T> inline bool MN(T &l,const T &r){return l>r?l=r,1:0;}
//#undef NUIP
#ifdef NUIP
#include "benri.h"
#else
#define out(args...)
#endif
#ifdef __cpp_init_captures
template<typename T>vector<T> table(int n, T v){ return vector<T>(n, v);}
template <class... Args> auto table(int n, Args... args){auto val = table(args...); return vector<decltype(val)>(n, move(val));}
#endif
template<class A,class B> pair<A,B> operator+(const pair<A,B> &p,const pair<A,B> &q){ return {p.X+q.X,p.Y+q.Y};}
template<class A,class B,class C,class D> pair<A,B>& operator+=(pair<A,B> &p,const pair<C,D> &q){ p.X+=q.X; p.Y+=q.Y; return p;}
template<class A,class B> pair<A,B> operator-(const pair<A,B> &p,const pair<A,B> &q){ return {p.X-q.X,p.Y-q.Y};}
template<class A,class B,class C,class D> pair<A,B>& operator-=(pair<A,B> &p,const pair<C,D> &q){ p.X-=q.X; p.Y-=q.Y; return p;}
template<class A,class B> istream& operator>>(istream &is, pair<A,B> &p){ is>>p.X>>p.Y; return is;}
template<class T=ll> T read(){ T re; cin>>re; return move(re);}
template<class T=ll> T read(const T &dec){ T re; cin>>re; return re-dec;}
template<class T=ll> vector<T> readV(const int sz){ vector<T> re(sz); for(auto &x:re) x=read<T>(); return move(re);}
template<class T=ll> vector<T> readV(const int sz, const T &dec){ vector<T> re(sz); for(auto &x:re) x=read<T>(dec); return move(re);}
vv<int> readG(const int &n,const int &m){ vv<int> g(n); rep(_,m){ cauto a=read<int>(1),b=read<int>(1); g[a].pb(b); g[b].pb(a);} return move(g);}
vv<int> readG(const int &n){ return readG(n,n-1);}
const ll MOD=1e9+7; //998244353

vector<int> getDiam(const vv<int> &g){
	const int n=g.size();
	int rt;
	{
		vector<int> d(n,MOD); d[0]=0;
		queue<int> que; que.emplace(0);
		while(que.size()){
			cauto v=que.front(); que.pop();
			for(auto w:g[v])if(MN(d[w],d[v]+1)) que.emplace(w);
		}
		int mx=-1;
		rep(v,n)if(MX(mx,d[v])) rt=v;
		out(d[3],mx,rt,1);
	}
	vector<int> re;
	{
		vector<pii> d(n,{MOD,0}); d[rt]={0,-1};
		queue<int> que; que.emplace(rt);
		while(que.size()){
			cauto v=que.front(); que.pop();
			for(auto w:g[v])if(MN(d[w],{d[v].X+1,v})) que.emplace(w);
		}
		pii mx{-1,0};
		re.eb();
		rep(v,n)if(MX(mx,d[v])) re.back()=v;
		out(d[3],re,rt,1);
		while(re.back()!=rt){
			cauto tmp=d[re.back()].Y;
			re.eb(tmp);
		}
		return re;
	}
}

vector<int> solve(const vv<int> &g){
	const int n=g.size();
	// if(n==3) return {0,1,2};
	cauto diam=getDiam(g);
	out(diam,1);
	cauto rt=diam[diam.size()/2];
	vector<int> re(n,MOD); re[rt]=0;
	queue<int> que; que.emplace(rt);
	while(que.size()){
		cauto v=que.front(); que.pop();
		for(auto w:g[v])if(MN(re[w],re[v]+1)) que.emplace(w);
	}
	for(auto &x:re) x%=3;
	if(diam.size()%2){
		auto dfs=
		[&](auto &&dfs,int v,int p)->void{
			if(re[v]) re[v]=3-re[v];
			for(auto w:g[v])if(w!=p) dfs(dfs,w,v);
		};
		dfs(dfs,rt,diam[diam.size()/2-1]);
	}else{
		auto dfs=
		[&](auto &&dfs,int v,int p)->void{
			re[v]=2-re[v];
			for(auto w:g[v])if(w!=p) dfs(dfs,w,v);
		};
		dfs(dfs,rt,diam[diam.size()/2-1]);
	}
	// out(re,1);
	return re;
}

int calc(const vv<int> &g, vector<int> cs){
	const int n=g.size();
	vector<array<int,3>> cnt(n,{0,0,0});
	int re=1;
	auto dfs=
		[&](auto &&dfs,int v,int p)->void{
			array<int,3> mx{0,0,0};
			for(auto w:g[v])if(w!=p){
				dfs(dfs,w,v);
				rep(i,3) MX(re,mx[i]+cnt[w][i]+(cs[v]==i));
				rep(i,3) out(v,w,i,mx,cnt[w],mx[i]+cnt[w][i]+(cs[v]==i),1);
				rep(i,3){
					MX(cnt[v][i],cnt[w][i]);
					MX(mx[i],cnt[w][i]);
				}
			}
			++cnt[v][cs[v]];
		};
	dfs(dfs,0,-1);
	return re;
}

mt19937 rnd(123);
vv<int> tree(int n){
	vv<int> g(n);
	vector<int> ind(n); iota(all(ind),0);
	shuffle(all(ind),rnd);
	reps(i,1,n){
		int a=ind[i];
		int b=ind[i-1];
		// while(b>0){
		// 	if(rnd()%2) break;
		// 	--b;
		// }
		g[a].pb(b);
		g[b].pb(a);
	}
	return g;
}

int main(){
  ios_base::sync_with_stdio(false); cin.tie(0);
  cout<<fixed<<setprecision(0);
	// cauto gg=tree(100000);
	// out(solve(gg),1); return 0;
// 	out(calc({{5,7}
// ,{7}
// ,{5,4}
// ,{6}
// ,{2}
// ,{0,2}
// ,{7,3}
// 						,{0,1,6}},{1,1,0,0,0,0,0,0}),1);
// 	return 0;
	if(0){
		const int N=12;
		vector<int> pw(N+1); pw[0]=1;
		rep(i,N) pw[i+1]=pw[i]*3;
		rep(_,1000){
			const int n=rand()%N+1;
			cauto g=tree(n);
			int best=n;
			vector<int> wit;
			rep(i,pw[n]){
				vector<int> v(n);
				rep(j,n) v[j]=i/pw[j]%3;
				if(MN(best,calc(g,v))) wit=v;
			}
			cauto ans=solve(g);
			int act=calc(g,ans);
			if(act!=best){
				out(g,ans,act,best,wit,1);
				rep(v,n)for(auto w:g[v])if(v<w) cout<<v<<" "<<w NL;
				exit(0);
			}
		}
		out("done",1);
		exit(0);
	}
	cauto n=read();
	cauto g=readG(n);
	cauto re=solve(g);
	cout<<calc(g,re) NL;
	for(auto x:re) cout<<"RGB"[x]; cout NL;
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 39764
final_rank: 10

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long long INF = 1e18;
//const ll mod = 1000000007;
ll dist[10][201000];
ll N;
vector<ll> edges[201000];
ll ans = 0;
char S[201000];
string RGB = "RGB";
vector<ll> dp[201000];

void dfs(int idx, int now, int from) {
    for(auto to : edges[now]) {
        if(to == from) continue;
        dist[idx][to] = dist[idx][now] + 1;
        dfs(idx, to, now);
    }
}

void dfs2(ll now, ll from) {
    for(int i = 0; i < 3; i++) {
        if(RGB[i] == S[now]) dp[now][i]++;
        chmax(ans, dp[now][i]);
    }
    for(auto to : edges[now]) {
        if(to == from) continue;
        dp[to] = dp[now];
        dfs2(to, now);
    }
}

void dfs3(int idx, int now, int from) {
    dist[idx][now] = 1;
    for(auto to : edges[now]) {
        if(to == from) continue;
        dfs3(idx, to, now);
        chmax(dist[idx][now], dist[idx][to] + 1);
    }
}

string T[2] = {"RGB", "GRB"};

void dfs4(string T, int idx, int now, int from) {
    S[now] = T[idx];
    for(auto to : edges[now]) {
        if(to == from) continue;
        dfs4(T, (idx + 1) % 3, to, now);
    }
}

void f(ll c) {
    map<ll, vector<ll>> mp;
    for(auto to : edges[c]) {
        mp[-dist[2][to]].push_back(to);
    }
    int parity = 0;
    for(auto tmp : mp) {
        ll d = -tmp.first;
        auto v = tmp.second;
        /*
        cerr << "- " << d << " -" << endl;
        for(auto tmp : v) {
            cerr << tmp << " ";
        }
        cerr << endl;
        */
        if(v.size() == 1) {
            ll len = 1 + 2 * d - 1;
            chmax(ans, (len + 2) / 3);
        } else if(v.size() == 2) {
            ll len = 1 + 2 * d;
            chmax(ans, (len + 2) / 3);
        } else {
            if(d % 3 == 0) {
                chmax(ans, 1 + (d / 3) * 2);
            } else {
                chmax(ans, (d + 2) / 3 * 2);
            }
        }
        for(auto to : v) {
            dfs4(T[parity], 0, to, c);
            parity = 1 - parity;
        }
    }
}


int main() {
    cin >> N;
    for(int i = 0; i < N - 1; i++) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }
    dist[0][0] = 0;
    dfs(0, 0, -1);
    ll B = 0;
    for(int i = 0; i < N; i++) {
        if(dist[0][i] > dist[0][B]) B = i;
    }
    dist[0][B] = 0;
    dfs(0, B, -1);
    ll A = 0;
    for(int i = 0; i < N; i++) {
        if(dist[0][A] < dist[0][i]) A = i;
    }
    dist[1][A] = 0;
    dfs(1, A, -1);
    ll c;
    for(int i = 0; i < N; i++) {
        if(dist[0][i] + dist[1][i] == dist[0][A] and abs(dist[0][i] - dist[1][i]) <= 1) {
            c = i;
        }
    }
    //cerr << A << " " << B << " " << c << endl;
    dfs3(2, c, -1);
    S[c] = 'B';
    f(c);
    dp[A] = {0, 0, 0};
    dfs2(A, -1);
    cout << ans << endl;
    for(int i = 0; i < N; i++) cout << S[i];
    cout << endl;
    return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 45576
final_rank: 12

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
//#include<atcoder/dsu>
//#include<atcoder/fenwicktree>
//#include<atcoder/math>
//#include<atcoder/maxflow>

using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m) {
	if (x >= m)x %= m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}


const int mn = 1 << 18;
struct edge {
	int to;
};
struct Data {
	int d, ma;
};
vector<edge> G[mn];
vector<int> ids[mn];
vector<Data> memo[mn];
int root;

Data merge(Data a, Data b) {
	Data res;
	//
	res.d = max(a.d, b.d);
	res.ma = max(a.ma, b.ma);
	//
	return res;
}

void add(P& p, int x) {
	if (p.first < x) {
		p.second = p.first;
		p.first = x;
	}
	else if (p.second < x)p.second = x;
}
Data dfs(int id, int fr) {
	Data res;
	//
	//initialize
	res = { 0,1 };
	P p = { 0,0 };
	//
	for (edge e : G[id]) {
		if (e.to == fr)continue;
		Data nex = dfs(e.to, id);
		//
		//update with edge
		//
		add(p, nex.d);
		res = merge(res, nex);
		ids[id].push_back(e.to);
		memo[id].push_back(nex);
	}
	
	//
	//update for return
    int s0 = p.first/ 3 + p.second / 3 + 1;
    int s1 = (p.first+2) / 3 + (p.second+2) / 3;
    res.ma = max({ res.ma,s0,s1 });
	res.d++;

	//
	return res;
}

int score[1 << 18];
void invdfs(int id, int fr, Data pre) {
	vector<Data> v;
	for (Data d : memo[id])v.push_back(d);
	if (fr >= 0)v.push_back(pre);
	int len = v.size();
	//
	P p = { 0,0 };
	//calcurate id's ans
	for (Data d : v) {
		score[id] = max(score[id], d.ma);
		add(p, d.d);
	}
	int s0 = p.first / 3 + p.second / 3 + 1;
	int s1 = (p.first+2) / 3 + (p.second+2) / 3;
	score[id] = max({ score[id],s0,s1 });
	//
	vector<Data> le(len + 1);
	vector<Data> ri(len + 1);
	vector<P> ple(len + 1);
	vector<P> pri(len + 1);
	//
	Data init_c = { 0,0 };
	//
	le[0] = init_c;
	ple[0] = { 0,0 };
	rep(i, len) {
		le[i + 1] = merge(le[i], v[i]);
		ple[i + 1] = ple[i]; add(ple[i + 1], v[i].d);

	}
	ri[len] = init_c;
	pri[len] = { 0,0 };
	per(i, len) {
		ri[i] = merge(ri[i + 1], v[i]);
		pri[i] = pri[i + 1]; add(pri[i], v[i].d);
	}
	rep(i, ids[id].size()) {
		int to = ids[id][i];
		Data d = merge(le[i], ri[i + 1]);

		//
		//update for return
		P p = { 0,0 };
		add(p, ple[i].first);
		add(p, ple[i].second);
		add(p, pri[i+1].first);
		add(p, pri[i+1].second);

		int s0 = p.first / 3 + p.second / 3 + 1;
		int s1 = (p.first+2) / 3 + (p.second+2) / 3;
		d.ma = max({ d.ma,s0,s1 });
		d.d++;
		//
		invdfs(to, id, d);
	}
}
void yaru() {
	dfs(root, -1);
	invdfs(root, -1, { 0,0 });
}



string s = "RGB";
string ans;
void dfs(int id, int fr, int col) {
	if (col == 3)col = 0;
	ans[id] = s[col];
	for (edge e : G[id])if (e.to != fr) {
		dfs(e.to, id, col + 1);
	}
}

int calcans() {
	int ma = 0;
	rep(i, 3) {
		function<int(int, int)> calc = [&](int id, int fr)->int {
			vector<int> ts;
			for (edge e : G[id])if (e.to != fr) {
				int nex = calc(e.to, id);
				ts.push_back(nex);
			}
			sort(all(ts), greater<int>());
			if (ts.size() >= 2) {
				int sum = ts[0] + ts[1];
				if (ans[id] == s[i])sum++;
				ma = max(ma, sum);
			}
			int res = 0;
			if (ts.size()) {
				res = ts[0];
			}
			if (ans[id] == s[i])res++;
			ma = max(ma, res);
			return res;
		}; calc(0, -1);
	}
	return ma;
}

void solve() {
	int n; cin >> n; ans.resize(n);
	rep(i, n - 1) {
		int a, b; cin >> a >> b; a--; b--;
		G[a].push_back({ b });
		G[b].push_back({ a });
	}
	yaru();
	int mi = mod;
	int chk = -1;
	rep(i, n) {
		if (mi > score[i]) {
			mi = score[i];
			chk = i;
		}
	}
	dfs(chk, -1, 0);
	int val = calcans();
	assert(mi == val);
	cout << mi << "\n";
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(15);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 106776
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n)  for(long long i=0;i<(long long)(n);i++)
#define REP(i,k,n) for(long long i=k;i<(long long)(n);i++)
#define all(a) a.begin(),a.end()
#define pb emplace_back
#define eb emplace_back
#define lb(v,k) (lower_bound(all(v),k)-v.begin())
#define ub(v,k) (upper_bound(all(v),k)-v.begin())
#define fi first
#define se second
#define pi M_PI
#define PQ(T) priority_queue<T>
#define SPQ(T) priority_queue<T,vector<T>,greater<T>>
#define dame(a) {out(a);return 0;}
#define decimal cout<<fixed<<setprecision(15);
#define dupli(a) {sort(all(a));a.erase(unique(all(a)),a.end());}
typedef long long ll;
typedef pair<ll,ll> P;
typedef tuple<ll,ll,ll> PP;
typedef tuple<ll,ll,ll,ll> PPP;
typedef multiset<ll> S;
using vi=vector<ll>;
using vvi=vector<vi>;
using vvvi=vector<vvi>;
using vvvvi=vector<vvvi>;
using vp=vector<P>;
using vvp=vector<vp>;
using vb=vector<bool>;
using vvb=vector<vb>;
const ll inf=1001001001001001001;
const ll INF=1001001001;
const ll mod=1000000007;
const double eps=1e-10;
template<class T> bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<class T> bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<class T> void out(T a){cout<<a<<'\n';}
template<class T> void outp(T a){cout<<'('<<a.fi<<','<<a.se<<')'<<'\n';}
template<class T> void outvp(T v){rep(i,v.size())cout<<'('<<v[i].fi<<','<<v[i].se<<')';cout<<'\n';}
template<class T> void outvvp(T v){rep(i,v.size())outvp(v[i]);}
template<class T> void outv(T v){rep(i,v.size()){if(i)cout<<' ';cout<<v[i];}cout<<'\n';}
template<class T> void outvv(T v){rep(i,v.size())outv(v[i]);}
template<class T> bool isin(T x,T l,T r){return (l)<=(x)&&(x)<=(r);}
template<class T> void yesno(T b){if(b)out("yes");else out("no");}
template<class T> void YesNo(T b){if(b)out("Yes");else out("No");}
template<class T> void YESNO(T b){if(b)out("YES");else out("NO");}
template<class T> void noyes(T b){if(b)out("no");else out("yes");}
template<class T> void NoYes(T b){if(b)out("No");else out("Yes");}
template<class T> void NOYES(T b){if(b)out("NO");else out("YES");}
void outs(ll a,ll b){if(a>=inf-100)out(b);else out(a);}
ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
ll modpow(ll a,ll b){ll res=1;a%=mod;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
vvi g;
vi diameter(){
    ll n=g.size(),ne;
    vi par(n,-1);
    P far(-1,0);
    rep(tt,2){
        vi dis(n,inf);
        queue<ll> q;
        ne=far.se;
        q.emplace(ne);
        dis[ne]=0;
        while(!q.empty()){
            auto t=q.front();q.pop();
            for(ll x:g[t]){
                if(chmin(dis[x],dis[t]+1)){
                    q.emplace(x);
                    par[x]=t;
                }
            }
        }
        far=P(-1,0);
        rep(i,n)chmax(far,P(dis[i],i));
    }
    ll w=far.se;
    vi res;
    while(w!=ne){
        res.pb(w);
        w=par[w];
    }
    res.pb(ne);
    return res;
}
vi ans;
void dfs0(int i,int p,int c){
    for(ll x:g[i])if(x!=p){
        ll nc=c-1;if(nc==-1)nc=2;
        ans[x]=nc;
        dfs0(x,i,nc);
    }
}
void dfs1(int i,int p,int c){
    for(ll x:g[i])if(x!=p){
        ll nc=c+1;if(nc==3)nc=0;
        ans[x]=nc;
        dfs1(x,i,nc);
    }
}
ll res=0;
vi dfs(int i,int p){
    vvi v(3);
    for(ll x:g[i])if(x!=p){
        auto t=dfs(x,i);
        rep(cnt,3)v[cnt].pb(t[cnt]);
    }
    rep(cnt,3){
        sort(all(v[cnt]));reverse(all(v[cnt]));
    }
    vi r(3),t(3);
    if(v[0].size())rep(c,3)r[c]=v[c][0];
    if(v[0].size()>1)rep(c,3)t[c]=v[c][0]+v[c][1];
    r[ans[i]]++;t[ans[i]]++;
    rep(c,3){chmax(res,r[c]);chmax(res,t[c]);}
    return r;
}
int main(){
    ll n;cin>>n;
    g=vvi(n);
    rep(i,n-1){
        ll a,b;cin>>a>>b;a--;b--;
        g[a].pb(b);g[b].pb(a);
    }
    vi d=diameter();
    // outv(d);
    ans=vi(n);
    rep(i,d.size()/2){
        ans[d[i]]=i%3;
        for(ll x:g[d[i]]){
            if((i!=d.size()-1&&x==d[i+1])||(i&&x==d[i-1]))continue;
            ans[x]=ans[d[i]]-1;
            if(ans[x]==-1)ans[x]=2;
            dfs0(x,d[i],ans[x]);
        }
    }
    REP(i,d.size()/2,d.size()){
        ans[d[i]]=i%3;
        for(ll x:g[d[i]]){
            if((i!=d.size()-1&&x==d[i+1])||(i&&x==d[i-1]))continue;
            ans[x]=ans[d[i]]+1;
            if(ans[x]==3)ans[x]=0;
            dfs1(x,d[i],ans[x]);
        }
    }
    // outv(ans);
    dfs(0,-1);
    out(res);
    for(ll x:ans){
        if(x==0)cout<<'R';
        if(x==1)cout<<'G';
        if(x==2)cout<<'B';
    }
    cout<<endl;
}
accuracy: 1
time_ms: 150
memory_kb: 60588
final_rank: 14

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define modulo N
#define mod(mod_x) ((((long long)mod_x+modulo))%modulo)
#define Inf 1000000000000000000
int Ans;
string S;
int N;
int D;
vector<vector<int>> E;
struct tree_diameter{
	const long long X = 1000000000000000000;
	pair<long long,vector<int>> get(vector<vector<pair<int,long long>>> &E){
		vector<long long> dis = bfs(E,0);
		long long maxi = -1;
		int ind = 0;
		for(int i=0;i<E.size();i++){
			if(dis[i]>maxi){
				maxi=dis[i];
				ind=i;
			}
		}

		dis = bfs(E,ind);
		maxi = -1;

		for(int i=0;i<E.size();i++){
			if(dis[i]>maxi){
				maxi=dis[i];
				ind=i;
			}
		}

		vector<int> ret;
		ret.push_back(ind);
		while(dis[ind]!=0LL){
			for(int i=0;i<E[ind].size();i++){
				if(dis[ind] == dis[E[ind][i].first] + E[ind][i].second){
					ind = E[ind][i].first;
					ret.push_back(ind);
					break;
				}
			}
		}
		
		return make_pair(maxi,ret);
		
	}
	
	pair<long long,vector<int>> get(vector<vector<int>> &E){
		vector<vector<pair<int,long long>>> e(E.size(),vector<pair<int,long long>>());
		for(int i=0;i<E.size();i++){
			for(int j=0;j<E[i].size();j++){
				e[i].emplace_back(E[i][j],1LL);
			}
		}
		return get(e);
	}
	
	vector<long long> bfs(vector<vector<pair<int,long long>>> &E,int start){
		vector<long long> dis(E.size(),X);
		dis[start] = 0LL;
		queue<int> Q;
		Q.push(start);
		
		while(Q.size()!=0){
			int u = Q.front();
			Q.pop();
			for(int i=0;i<E[u].size();i++){
				int v = E[u][i].first;
				if(dis[v]!=X)continue;
				dis[v] = dis[u] + E[u][i].second;
				Q.push(v);
			}
		}
		return dis;
	}
	
};
vector<int> maxi;

void dfs(int now,int p){
	rep(i,E[now].size()){
		int to = E[now][i];
		if(to==p)continue;
		dfs(to,now);
		maxi[now] = max(maxi[to] + 1,maxi[now]);
	}
}
string s = "RGB";
void dfs2(int now,int p,int ind,int d){
	S[now] = s[ind];
	if(d==0){
		vector<int> t;
		rep(i,E[now].size()){
			t.push_back(maxi[E[now][i]]);
		}
		sort(t.rbegin(),t.rend());
		int x = 1;
		int cnt = 0;
		rep(i,E[now].size()){
			int to = E[now][i];
			if(maxi[to]>=t[0]){
				cnt++;
				x*=-1;
			}
			int iind = ind + 3 + x;
			iind %= 3;
			dfs2(to,now,iind,x);
		}
		Ans = (D+2)/3;
		if(cnt>=3){
			if(D%3==0)Ans++;
		}
			
	}
	else{
		ind += d+3;
		ind %= 3;
		rep(i,E[now].size()){
			int to = E[now][i];
			if(to==p)continue;
			dfs2(to,now,ind,d);
		}
	}
}
int main(){
	
	cin>>N;
	S.resize(N,'.');
	E.resize(N,vector<int>());
	rep(i,N-1){
		int a,b;
		scanf("%d %d",&a,&b);
		a--;b--;
		E[a].push_back(b);
		E[b].push_back(a);
		
	}
	
	tree_diameter T;
	vector<int> X = T.get(E).second;
	D = X.size();
	if(N==1){
		S = "R";
		Ans = 1;
	}
	else if(N==2){
		S = "RG";
		Ans = 1;
	}
	else{
		int f = X[X.size()/2];
		maxi.resize(N,0);
		dfs(f,-1);
		dfs2(f,-1,0,0);
	}
	
	cout<<Ans<<endl;
	cout<<S<<endl;
	
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 37852
final_rank: 9

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
//#include<atcoder/dsu>
//#include<atcoder/fenwicktree>
//#include<atcoder/math>
//#include<atcoder/maxflow>

using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m) {
	if (x >= m)x %= m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}

string s = "RGB";
string ans;
vector<int> G[1 << 18];
void dfs(int id, int fr, int col) {
	if (col == 3)col = 0;
	ans[id] = s[col];
	for (int to : G[id])if (to != fr) {
		dfs(to, id, col + 1);
	}
}

int calcans() {
	int ma = 0;
	rep(i, 3) {
		function<int(int, int)> calc = [&](int id, int fr)->int {
			vector<int> ts;
			for (int to : G[id])if (to != fr) {
				int nex = calc(to, id);
				ts.push_back(nex);
			}
			sort(all(ts), greater<int>());
			if (ts.size() >= 2) {
				int sum = ts[0] + ts[1];
				if (ans[id] == s[i])sum++;
				ma = max(ma, sum);
			}
			int res = 0;
			if (ts.size()) {
				res = ts[0];
			}
			if (ans[id] == s[i])res++;
			ma = max(ma, res);
			return res;
		}; calc(0, -1);
	}
	return ma;
}

void solve() {
	int n; cin >> n; ans.resize(n);
	rep(i, n - 1) {
		int a, b; cin >> a >> b; a--; b--;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	int mi = mod;
	int chk = -1;
	mt19937 mt(time(0));
	uniform_int_distribution<> ud(0, n - 1);
	rep(i, 100) {
		int r = ud(mt);
		dfs(r, -1, 0);
		if (mi > calcans()) {
			mi = calcans();
			chk = r;
		}
	}
	dfs(chk, -1, 0);
	cout << mi << "\n";
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(15);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 0.4222222222222222
time_ms: 1840
memory_kb: 13004
final_rank: 20

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define modulo N
#define mod(mod_x) ((((long long)mod_x+modulo))%modulo)
#define Inf 1000000000000000000
int Ans;
string S;
int N;
int D;
vector<vector<int>> E;
struct tree_diameter{
	const long long X = 1000000000000000000;
	pair<long long,vector<int>> get(vector<vector<pair<int,long long>>> &E){
		vector<long long> dis = bfs(E,0);
		long long maxi = -1;
		int ind = 0;
		for(int i=0;i<E.size();i++){
			if(dis[i]>maxi){
				maxi=dis[i];
				ind=i;
			}
		}

		dis = bfs(E,ind);
		maxi = -1;

		for(int i=0;i<E.size();i++){
			if(dis[i]>maxi){
				maxi=dis[i];
				ind=i;
			}
		}

		vector<int> ret;
		ret.push_back(ind);
		while(dis[ind]!=0LL){
			for(int i=0;i<E[ind].size();i++){
				if(dis[ind] == dis[E[ind][i].first] + E[ind][i].second){
					ind = E[ind][i].first;
					ret.push_back(ind);
					break;
				}
			}
		}
		
		return make_pair(maxi,ret);
		
	}
	
	pair<long long,vector<int>> get(vector<vector<int>> &E){
		vector<vector<pair<int,long long>>> e(E.size(),vector<pair<int,long long>>());
		for(int i=0;i<E.size();i++){
			for(int j=0;j<E[i].size();j++){
				e[i].emplace_back(E[i][j],1LL);
			}
		}
		return get(e);
	}
	
	vector<long long> bfs(vector<vector<pair<int,long long>>> &E,int start){
		vector<long long> dis(E.size(),X);
		dis[start] = 0LL;
		queue<int> Q;
		Q.push(start);
		
		while(Q.size()!=0){
			int u = Q.front();
			Q.pop();
			for(int i=0;i<E[u].size();i++){
				int v = E[u][i].first;
				if(dis[v]!=X)continue;
				dis[v] = dis[u] + E[u][i].second;
				Q.push(v);
			}
		}
		return dis;
	}
	
};
vector<int> maxi;

void dfs(int now,int p){
	rep(i,E[now].size()){
		int to = E[now][i];
		if(to==p)continue;
		dfs(to,now);
		maxi[now] = max(maxi[to] + 1,maxi[now]);
	}
}
string s = "RGB";
void dfs2(int now,int p,int ind,int d){
	S[now] = s[ind];
	if(d==0){
		vector<int> t;
		rep(i,E[now].size()){
			t.push_back(maxi[E[now][i]]);
		}
		sort(t.rbegin(),t.rend());
		int x = 1;
		int cnt = 0;
		rep(i,E[now].size()){
			int to = E[now][i];
			if(maxi[to]>=t[1]){
				cnt++;
				x*=-1;
			}
			int iind = ind + 3 + x;
			iind %= 3;
			dfs2(to,now,iind,x);
		}
		Ans = (D+2)/3;
		if(cnt>=3){
			if(D%3==0)Ans++;
		}
			
	}
	else{
		ind += d+3;
		ind %= 3;
		rep(i,E[now].size()){
			int to = E[now][i];
			if(to==p)continue;
			dfs2(to,now,ind,d);
		}
	}
}
int main(){
	
	cin>>N;
	S.resize(N,'.');
	E.resize(N,vector<int>());
	rep(i,N-1){
		int a,b;
		scanf("%d %d",&a,&b);
		a--;b--;
		E[a].push_back(b);
		E[b].push_back(a);
		
	}
	
	tree_diameter T;
	vector<int> X = T.get(E).second;
	D = X.size();
	if(N==1){
		S = "R";
		Ans = 1;
	}
	else if(N==2){
		S = "RG";
		Ans = 1;
	}
	else{
		int f = X[X.size()/2];
		maxi.resize(N,0);
		dfs(f,-1);
		dfs2(f,-1,0,0);
	}
	
	cout<<Ans<<endl;
	cout<<S<<endl;
	
    return 0;
}
accuracy: 0.4888888888888889
time_ms: 40
memory_kb: 29820
final_rank: 19

code_snippet: //#define NDEBUG

#pragma region cp_template

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>

namespace n91 {

  using i32 = std::int32_t;
  using i64 = std::int64_t;
  using u32 = std::uint32_t;
  using u64 = std::uint64_t;
  using isize = std::ptrdiff_t;
  using usize = std::size_t;

  struct rep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { ++i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr rep(const usize f, const usize l) noexcept
      : f(std::min(f, l)), l(l) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };
  struct revrep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { --i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr revrep(const usize f, const usize l) noexcept
      : f(l - 1), l(std::min(f, l) - 1) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };
  template <class T> auto md_vec(const usize n, const T& value) {
    return std::vector<T>(n, value);
  }
  template <class... Args> auto md_vec(const usize n, Args... args) {
    return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
  }
  template <class T> constexpr T difference(const T& a, const T& b) noexcept {
    return a < b ? b - a : a - b;
  }
  template <class T> void chmin(T& a, const T& b) noexcept {
    if (b < a)
      a = b;
  }
  template <class T> void chmax(T& a, const T& b) noexcept {
    if (a < b)
      a = b;
  }
  template <class F> class rec_lambda {
    F f;

  public:
    rec_lambda(F&& f) : f(std::move(f)) {}
    template <class... Args> auto operator()(Args&&... args) const {
      return f(*this, std::forward<Args>(args)...);
    }
  };
  template <class F> auto make_rec(F&& f) { return rec_lambda<F>(std::move(f)); }
  template <class T> T scan() {
    T ret;
    std::cin >> ret;
    return ret;
  }
  constexpr char eoln = '\n';
  template <class T> T ceildiv(const T& l, const T& r) {
    return l / r + (l % r != 0 ? 1 : 0);
  }

} // namespace n91

#pragma endregion cp_template

#include <cstdint>

template <std::uint_fast64_t mod> class modint {
  using u64 = std::uint_fast64_t;

public:
  u64 v;

  constexpr modint(const u64 x = 0) noexcept : v(x% mod) {}
  constexpr modint operator+(const modint rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint& operator+=(const modint rhs) noexcept {
    v += rhs.v;
    if (v >= mod)
      v -= mod;
    return *this;
  }
  constexpr modint& operator-=(const modint rhs) noexcept {
    if (v < rhs.v)
      v += mod;
    v -= rhs.v;
    return *this;
  }
  constexpr modint& operator*=(const modint rhs) noexcept {
    v = v * rhs.v % mod;
    return *this;
  }
  constexpr modint& operator/=(modint rhs) noexcept {
    u64 exp = mod - 2;
    while (exp != 0) {
      if (exp % 2 != 0)
        *this *= rhs;
      rhs *= rhs;
      exp /= 2;
    }
    return *this;
  }
};

#include <functional>
#include <utility>

namespace n91 {

  template <class T, class U, class Operate = std::multiplies<T>>
  constexpr T power(T base, U exp, const Operate& oper = Operate(), T iden = 1) {
    while (exp != 0) {
      if (exp % 2 != 0) {
        iden = oper(iden, base);
      }
      exp /= 2;
      base = oper(base, base);
    }
    return iden;
  }

} // namespace n91

namespace n91 {

  void main_() {
    using mint = modint<998244353>;
    /*
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    //*/
    const usize n = scan<usize>();
    auto g = md_vec(n, 0, usize());
    for (const usize i : rep(0, n - 1)) {
      const usize a = scan<usize>() - 1;
      const usize b = scan<usize>() - 1;
      g[a].push_back(b);
      g[b].push_back(a);
    }
    std::vector<usize> dist(n, 0), par(n);
    const auto dfs = [&](const auto& dfs, const usize v, const usize p) -> void {
      par[v] = p;
      for (const auto e : g[v]) {
        if (e != p) {
          dist[e] = dist[v] + 1;
          dfs(dfs, e, v);
        }
      }
    };
    dfs(dfs, 0, n);
    const usize d0 = std::max_element(dist.begin(), dist.end()) - dist.begin();
    dist[d0] = 0;
    dfs(dfs, d0, n);
    const usize d1 = std::max_element(dist.cbegin(), dist.cend()) - dist.begin();
    const usize diam = dist[d1];
    usize ans_x;
    std::vector<u32> ans(n);
    if (diam % 2 == 1) {
      usize c1 = d1;
      for (const usize i : rep(0, diam / 2)) {
        c1 = par[c1];
      }
      usize c0 = par[c1];
      ans_x = diam / 3 + 1;
      dist[c0] = 0;
      dist[c1] = n;
      dfs(dfs, c0, c1);
      dfs(dfs, c1, c0);
      for (const usize i : rep(0, n)) {
        if (dist[i] >= n) {
          ans[i] = 2 - (dist[i] - n) % 3;
        }
        else {
          ans[i] = dist[i] % 3;
        }
      }
    }
    else {
      usize c = d1;
      for (const usize i : rep(0, diam / 2)) {
        c = par[c];
      }
      dfs(dfs, c, n);
      dist[c] = 0;
      bool fl = false;
      for (const usize v : g[c]) {
        if (fl) {
          dist[v] = n;
        }
        else {
          dist[v] = 1;
        }
        dfs(dfs, v, c);
        fl = !fl;
      }
      for (const usize i : rep(0, n)) {
        if (dist[i] >= n) {
          ans[i] = 2 - (dist[i] - n) % 3;
        }
        else {
          ans[i] = dist[i] % 3;
        }
      }
    }
    std::vector<usize> c_dist(n, 0);
    const auto c_dfs = [&](const auto& c_dfs, const usize v, const usize p,
      const usize col) -> void {
        if (ans[v] == col) {
          ++c_dist[v];
        }
        for (const auto e : g[v]) {
          if (e != p) {
            c_dist[e] = c_dist[v];
            c_dfs(c_dfs, e, v, col);
          }
        }
    };
    ans_x = 0;
    for (const usize i : rep(0, 3)) {
      c_dist[0] = 0;
      c_dfs(c_dfs, 0, n, i);
      const usize c_d0 =
        std::max_element(c_dist.begin(), c_dist.end()) - c_dist.begin();
      c_dist[c_d0] = 0;
      c_dfs(c_dfs, c_d0, n, i);
      chmax(ans_x, *std::max_element(c_dist.cbegin(), c_dist.cend()));
    }

    std::cout << ans_x << eoln;
    for (const auto e : ans) {
      if (e % 3 == 0) {
        std::cout << "R";
      }
      else if (e % 3 == 1) {
      std::cout << "G";
      }
      else {
        std::cout << "B";
      }
    }
    std::cout << eoln;
  }

} // namespace n91

int main() {
  n91::main_();
  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 35072
final_rank: 11

code_snippet: #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using uint = unsigned;
using pcc = pair<char, char>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using tuplis = array<ll, 3>;
template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;
const ll LINF=0x1fffffffffffffff;
const ll MINF=0x7fffffffffff;
const int INF=0x3fffffff;
const int MOD=1000000007;
const int MODD=998244353;
const ld DINF=numeric_limits<ld>::infinity();
const ld EPS=1e-9;
const ld PI=3.1415926535897932;
const ll dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const ll dy[] = {1, 0, -1, 0, 1, 1, -1, -1};
#define overload4(_1,_2,_3,_4,name,...) name
#define overload3(_1,_2,_3,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep4(i,a,b,c) for(ll i=(a)+((b)-(a)-1)/(c)*(c);i>=(a);i-=c)
#define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define each1(i,a) for(auto&&i:a)
#define each2(x,y,a) for(auto&&[x,y]:a)
#define each3(x,y,z,a) for(auto&&[x,y,z]:a)
#define each(...) overload4(__VA_ARGS__,each3,each2,each1)(__VA_ARGS__)
#define all1(i) begin(i),end(i)
#define all2(i,a) begin(i),begin(i)+a
#define all3(i,a,b) begin(i)+a,begin(i)+b
#define all(...) overload3(__VA_ARGS__,all3,all2,all1)(__VA_ARGS__)
#define rall1(i) (i).rbegin(),(i).rend()
#define rall2(i,k) (i).rbegin(),(i).rbegin()+k
#define rall3(i,a,b) (i).rbegin()+a,(i).rbegin()+b
#define rall(...) overload3(__VA_ARGS__,rall3,rall2,rall1)(__VA_ARGS__)
#define sum(...) accumulate(all(__VA_ARGS__),0LL)
#define dsum(...) accumulate(all(__VA_ARGS__),0.0L)
#define Msum(...) accumulate(all(__VA_ARGS__),0_M)
#define elif else if
#define unless(a) if(!(a))
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)
#define Sort(a) sort(all(a))
#define Rev(a) reverse(all(a))
#define Uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define vv(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }
inline ll popcnt(ull a){ return __builtin_popcountll(a); }
ll gcd(ll a, ll b){ while(b){ ll c = b; b = a % b; a = c; } return a; }
ll lcm(ll a, ll b){ if(!a || !b) return 0; return a * b / gcd(a, b); }
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
template<class T> bool chmin(T& a, const T& b){ if(a > b){ a = b; return 1; } return 0; }
template<class T> bool chmax(T& a, const T& b){ if(a < b){ a = b; return 1; } return 0; }
template<class T, class U> bool chmin(T& a, const U& b){ if(a > T(b)){ a = b; return 1; } return 0; }
template<class T, class U> bool chmax(T& a, const U& b){ if(a < T(b)){ a = b; return 1; } return 0; }
vector<ll> iota(ll n){ vector<ll> a(n); iota(a.begin(), a.end(), 0); return a; }
vector<pll> factor(ull x){ vector<pll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
map<ll,ll> factor_map(ull x){ map<ll,ll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans[i] = 1; while((x /= i) % i == 0) ans[i]++; } if(x != 1) ans[x] = 1; return ans; }
vector<ll> divisor(ull x){ vector<ll> ans; for(ull i = 1; i * i <= x; i++) if(x % i == 0) ans.push_back(i); rrep(ans.size() - (ans.back() * ans.back() == x)) ans.push_back(x / ans[i]); return ans; }
template<class T> unordered_map<T, ll> press(vector<T> a){ Uniq(a); unordered_map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
template<class T> map<T, ll> press_map(vector<T> a){ Uniq(a); map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
int scan(){ return getchar(); }
void scan(int& a){ scanf("%d", &a); }
void scan(unsigned& a){ scanf("%u", &a); }
void scan(long& a){ scanf("%ld", &a); }
void scan(long long& a){ scanf("%lld", &a); }
void scan(unsigned long long& a){ scanf("%llu", &a); }
void scan(char& a){ do{ a = getchar(); }while(a == ' ' || a == '\n'); }
void scan(float& a){ scanf("%f", &a); }
void scan(double& a){ scanf("%lf", &a); }
void scan(long double& a){ scanf("%Lf", &a); }
void scan(vector<bool>& a){ for(unsigned i = 0; i < a.size(); i++){ int b; scan(b); a[i] = b; } }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto&& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto&& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto&& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto&& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){ scan(head); in(tail...); }
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(unsigned a){ printf("%u", a); }
void print(long a){ printf("%ld", a); }
void print(long long a){ printf("%lld", a); }
void print(unsigned long long a){ printf("%llu", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(const char a[]){ printf("%s", a); }
void print(float a){ printf("%.15f", a); }
void print(double a){ printf("%.15f", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
template<class T> void print(const complex<T>& a){ if(a.real() >= 0) print('+'); print(a.real()); if(a.imag() >= 0) print('+'); print(a.imag()); print('i'); }
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ print(p.first); putchar(' '); print(p.second); }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ putchar(' '); print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
#ifdef DEBUG
inline ll __lg(ull __n){ return sizeof(ull) * __CHAR_BIT__  - 1 - __builtin_clzll(__n); }
#define debug(...) { print(#__VA_ARGS__); print(":"); out(__VA_ARGS__); }
#else
#define debug(...) void(0)
#endif
int first(bool i = true){ return out(i?"first":"second"); }
int yes(bool i = true){ return out(i?"yes":"no"); }
int Yes(bool i = true){ return out(i?"Yes":"No"); }
int No(){ return out("No"); }
int YES(bool i = true){ return out(i?"YES":"NO"); }
int NO(){ return out("NO"); }
int Yay(bool i = true){ return out(i?"Yay!":":("); }
int possible(bool i = true){ return out(i?"possible":"impossible"); }
int Possible(bool i = true){ return out(i?"Possible":"Impossible"); }
int POSSIBLE(bool i = true){ return out(i?"POSSIBLE":"IMPOSSIBLE"); }
void Case(ll i){ printf("Case #%lld: ", i); }



struct UnWeightedEdge{
    ll to;
    static constexpr ll cost = 1;
    UnWeightedEdge(){}
    UnWeightedEdge(ll to): to(to){}
    operator ll() const { return to; }
};
struct UnWeightedGraph{
    using E = UnWeightedEdge;
    vector<vector<E>> g;
    UnWeightedGraph(){}
    UnWeightedGraph(ll n): g(n){}
    vector<E>& operator[](ll at){ return g[at]; }
    operator vector<vector<E>>&(){ return g; }
    auto begin(){ return g.begin(); }
    auto end(){ return g.end(); }
    auto begin() const { return g.cbegin(); }
    auto end() const { return g.cend(); }
    ll size() const { return g.size(); }
    void resize(ll n){ g.resize(n); }
    const vector<E>& operator[](ll at) const { return g[at]; }
    operator const vector<vector<E>>&() const { return g; }
    void add_edge(ll a, ll b){
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    void add_directed_edge(ll from, ll to){
        g[from].emplace_back(to);
    }
    template<ll start_index = 1, bool directed = false> void input_graph(ll m){
        while(m--){
            ll a, b;
            scanf("%lld%lld", &a, &b);
            a -= start_index;
            b -= start_index;
            g[a].emplace_back(b);
            if(!directed) g[b].emplace_back(a);
        }
    }
    template<ll start_index = 1> void input_tree(ll n = -1){ if(n == -1) n = g.size(); input_graph<start_index>(n - 1); }
};
vector<ll> Diameter(const UnWeightedGraph& g){
    ll n = g.size();
    vector<ll> cost(n, LINF);
    queue<ll> q;
    cost[0] = 0;
    q.push(0);
    ll d1 = 0;
    while(q.size()){
        d1 = q.front();
        q.pop();
        each(i, g[d1]) if(chmin(cost[i], cost[d1] + 1)) q.push(i);
    }
    cost.assign(n, LINF);
    vector<ll> back(n, -1);
    cost[d1] = 0;
    q.push(d1);
    ll d2 = 0;
    while(q.size()){
        d2 = q.front();
        q.pop();
        each(i, g[d2]) if(chmin(cost[i], cost[d2] + 1)){
            back[i] = d2;
            q.push(i);
        }
    }
    vector<ll> ans = {d2};
    while(ans.back() != d1) ans.push_back(back[ans.back()]);
    return ans;
}
vector<ll> BFS(const UnWeightedGraph& g, ll start){
    vector<ll> cost(g.size(), LINF);
    queue<ll> q;
    cost[start] = 0;
    q.push(start);
    while(q.size()){
        ll at = q.front();
        q.pop();
        each(i, g[at]) if(chmin(cost[i], cost[at] + i.cost)) q.push(i);
    }
    return cost;
}
signed main(){
    LL(n);
    if(n==1){
        out(1);
        return out('R');
    }
    UnWeightedGraph g(n);
    g.input_tree();
    auto d=Diameter(g);
    string color(n,'-');
    auto cost1=BFS(g,d[(d.size()-1)/2]),cost2=BFS(g,d[(d.size()+1)/2]);
    rep(n)color[i]=cost1[i]<cost2[i]?"BGR"[cost1[i]%3]:"RGB"[cost2[i]%3];
    ll ans=0;
    for(char c:"RGB"s){
        vec(pll,dp,n);
        auto dfs = [&](ll from, ll at, auto dfs) -> void {
            each(i, g[at]) if(i != from){
                dfs(at, i, dfs);
                if(chmax(dp[at].second,dp[i].first+(color[i]==c))&&dp[at].first<dp[at].second)swap(dp[at].first,dp[at].second);
            }
        };
        dfs(-1, 0, dfs);
        auto dfs2 = [&](ll from, ll at, auto dfs) -> void {
            each(i, g[at]) if(i != from){
                const ll a=dp[at].first==dp[i].first+(color[i]==c)?dp[at].second:dp[at].first;
                if(chmax(dp[i].second,a+(color[at]==c))&&dp[i].first<dp[i].second)swap(dp[i].first,dp[i].second);
                dfs(at, i, dfs);
            }
        };
        dfs2(-1, 0, dfs2);
        rep(n)chmax(ans,dp[i].first+dp[i].second+(color[i]==c));
    }
    out(ans);
    out(color);
}
accuracy: 1
time_ms: 170
memory_kb: 53488
final_rank: 13