#include <bits/stdc++.h>
using namespace std;
const long double EPS = 1e-10;
const long long MOD = 1e9 + 7;
const long long INF = 1e18;
const long double PI = 3.1415926535897932384626433832795028841;
map<string, int> ssol;
void checkAdd(string vs) {
  if (ssol.find(vs) != ssol.end()) {
    return;
  }
  ssol[vs] = 1;
}
bool TST = 0;
long long powmod(long long a, long long b) {
  long long res = 1;
  a %= MOD;
  for (; b; b >>= 1) {
    if (b & 1) res = res * a % MOD;
    a = a * a % MOD;
  }
  return res;
}
void Show(int *QQ, int N) {
  if (not TST) {
    return;
  }
  for (int x = 0; x < N; x++) {
    cout << QQ[x];
    if (x != N - 1) {
      cout << ',';
    }
  }
  cout << '\n';
}
void ShowLL(long long *QQ, int N) {
  if (not TST) {
    return;
  }
  for (int x = 0; x < N; x++) {
    cout << QQ[x];
    if (x != N - 1) {
      cout << ',';
    }
  }
  cout << '\n';
}
const int maxn = 1e6 + 20;
const int maxl = 30;
int n;
int act;
int sz[maxn], lvl[maxn];
int clen[maxl][maxn];
int maxlvl = 1;
vector<int> conn[maxn];
vector<int> nlvl[maxn];
int compute_sz(int head_small, int head_big) {
  int ans = 1;
  for (int l = 0; l < maxl; l++) {
    if (clen[l][head_small] != -1 and clen[l][head_big] != -1) {
      ans += compute_sz(clen[l][head_small], clen[l][head_big]);
    } else if (clen[l][head_small] != -1) {
      ans += sz[clen[l][head_small]];
    } else if (clen[l][head_big] != -1) {
      ans += sz[clen[l][head_big]];
    }
  }
  return ans;
}
int generate(vector<int> nodes) {
  int top = act++;
  sz[top] = 1;
  for (int l = 0; l < maxl; l++) {
    vector<int> list;
    for (int i = 0; i < nodes.size(); i++) {
      if (clen[l][nodes[i]] != -1) list.push_back(clen[l][nodes[i]]);
    }
    if (list.size() > 1) {
      clen[l][top] = generate(list);
    } else if (list.size() == 1) {
      clen[l][top] = list[0];
    } else {
      clen[l][top] = -1;
    }
    if (clen[l][top] != -1) sz[top] += sz[clen[l][top]];
  }
  return top;
}
void dfs(int i, int depth) {
  sz[i] = 1;
  lvl[i] = depth;
  nlvl[lvl[i]].push_back(i);
  maxlvl = max(maxlvl, depth);
  for (int j = 0; j < conn[i].size(); j++) {
    dfs(conn[i][j], depth + 1);
    sz[i] += sz[conn[i][j]];
  }
}
int try_on(int i) {
  if (conn[i].size() == 0) return 1;
  if (conn[i].size() == 1) return sz[i] - 1;
  int big = -1;
  int bignum = 0;
  for (int j = 0; j < conn[i].size(); j++) {
    if (sz[conn[i][j]] > bignum) {
      bignum = sz[conn[i][j]];
      big = j;
    }
  }
  vector<int> list;
  for (int j = 0; j < conn[i].size(); j++) {
    if (j == big) continue;
    list.push_back(conn[i][j]);
  }
  int head_small = generate(list);
  int size_new = compute_sz(head_small, conn[i][big]);
  act = n;
  return size_new;
}
int process(int lvl) {
  int total = sz[0];
  for (int i = 0; i < nlvl[lvl].size(); i++) {
    int foo = try_on(nlvl[lvl][i]);
    total -= sz[nlvl[lvl][i]];
    total += foo;
  }
  return total;
}
int main() {
  scanf("%d", &n);
  act = n;
  for (int i = 0; i < maxl; i++) fill(clen[i], clen[i] + n, -1);
  for (int i = 0; i < n - 1; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    char x;
    cin >> x;
    conn[u].push_back(v);
    clen[x - 'a'][u] = v;
  }
  dfs(0, 1);
  int best_ans = INT_MAX;
  int i_ans = -1;
  for (int i = 1; i <= maxlvl; i++) {
    int ans = process(i);
    if (ans < best_ans) {
      best_ans = ans;
      i_ans = i;
    }
  }
  printf("%d\n%d", best_ans, i_ans);
}
