#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<sstream>
#include<cassert>
using namespace std;
const int maxn = 200 + 5;
const int INF = 1000000000;
struct Edge {
int u, v, d;//d=1 u->v;d=2 v->u;d=0 u-v;
Edge(int u = 0,int v=0,int d=0):u(u),v(v),d(d){}
};
vector<Edge>edges[maxn];
int n, root, maxlen, f[maxn], g[maxn], have_father[maxn];
bool read_data() {
bool have_data = false;
int a, b;
n = 0;
for (int i = 0; i < maxn; i++)edges[i].clear();
memset(have_father, 0, sizeof(have_father));
while (cin >> a && a) {
string str;
have_data = true;
if (a > n)n = a;
while (cin >> str && str != "0") {
int len = str.length();
char dir = str[len - 1];
if (dir == 'd' || dir == 'u')str = str.substr(0, len - 1);
stringstream ss(str);
ss >> b;
if (b > n)n = b;
have_father[b] = 1;
if (dir == 'd') {
edges[a].push_back(Edge(a, b, 1));
edges[b].push_back(Edge(b, a, 2));
}
else if (dir == 'u') {
edges[a].push_back(Edge(a, b, 2));
edges[b].push_back(Edge(b, a, 1));
}
else {
edges[a].push_back(Edge(a, b, 0));
}
}
}
if (have_data) {
for (int i = 1; i <= n; i++) {
if (!have_father[i] && !edges[i].empty()) {
root = i; break;
}
}
}
return have_data;
}
struct UndirectedSon {
int w, f, g;
UndirectedSon(int w = 0, int f = 0,int g=0):w(w),f(f),g(g){}
};
bool cmp_f(const UndirectedSon& w1, const UndirectedSon& w2) {
return w1.f < w2.f;
}
bool cmp_g(const UndirectedSon& w1, const UndirectedSon& w2) {
return w1.g < w2.g;
}
bool dp(int i, int fa) {
if (edges[i].empty()) {
f[i] = g[i] = 0;
return true;
}
vector<UndirectedSon>sons;
int f0 = 0, g0 = 0;
for (int k = 0; k < edges[i].size(); k++) {
int w = edges[i][k].v;
if (w == fa)continue;
dp(w, i);
int d = edges[i][k].d;
if (d == 0)sons.push_back(UndirectedSon(w, f[w], g[w]));
else if (d == 1)g0 = max(g0, g[w] + 1);
else f0 = max(f0, f[w] + 1);
}
if (sons.empty()) {
f[i] = f0; g[i] = g0;
if (f[i] + g[i] > maxlen) {
f[i] = g[i] = INF;
}
return f[i] < INF;
}
f[i] = g[i] = INF;
int s = sons.size();
sort(sons.begin(), sons.end(), cmp_f);
int maxg[maxn];
maxg[s - 1] = sons[s - 1].g;
for (int k = s - 2; k >= 0; k--) {
maxg[k] = max(sons[k].g, maxg[k + 1]);
}
for (int p = 0; p <= sons.size(); p++) {
int ff = f0, gg = g0;
if (p > 0)ff = max(ff, sons[p - 1].f + 1);
if (p < sons.size())gg = max(gg, maxg[p] + 1);
if (ff + gg <= maxlen)f[i] = min(f[i], ff);
}
sort(sons.begin(), sons.end(), cmp_g);
int maxf[maxn]; // maxf[i] is max{sons[i].f, sons[i+1].f, ...}
maxf[s - 1] = sons[s - 1].f;
for (int k = s - 2; k >= 0; k--)
maxf[k] = max(sons[k].f, maxf[k + 1]);
for (int p = 0; p <= sons.size(); p++) {
int ff = f0, gg = g0;
if (p > 0) gg = max(gg, sons[p - 1].g + 1);
if (p < sons.size()) ff = max(ff, maxf[p] + 1);
if (ff + gg <= maxlen) g[i] = min(g[i], gg);
}
return f[i] < INF;
}
int dfs(int u) {
int ans = 0;
for (int i = 0; i < edges[u].size(); i++) {
int v = edges[u][i].v;
if (edges[u][i].d == 1) {
ans = max(ans, dfs(v) + 1);
}
}
return ans;
}
int main() {
while (read_data()) {
maxlen = 0;
for (int i = 1; i <= n; i++)maxlen = max(maxlen, dfs(i));
if (dp(root, -1))cout << maxlen + 1 << endl;
else cout << maxlen + 2 << endl;
}
return 0;
}