#include <bits/stdc++.h>
using namespace std;
mt19937_64 gen(chrono::high_resolution_clock::now().time_since_epoch().count());
template <typename T>
T randInt(T min, T max) {
  uniform_int_distribution<T> dist(min, max);
  return dist(gen);
}
template <typename T>
T randDouble(T min, T max) {
  uniform_real_distribution<T> dist(min, max);
  return dist(gen);
}
double workTime() { return double(clock()) / CLOCKS_PER_SEC; }
void myReturn(int code = 0) { exit(code); }
struct v {
  string name;
  int version;
  vector<pair<string, int> > deps;
  v(string name, int version) : name(name), version(version) {}
};
vector<v> G;
int main() {
  cin.sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    string name;
    int version;
    cin >> name >> version;
    G.push_back(v(name, version));
    int deps;
    cin >> deps;
    for (int j = 0; j < deps; j++) {
      string n;
      int v;
      cin >> n >> v;
      G[i].deps.push_back({n, v});
    }
    getline(cin, name);
    getline(cin, name);
  }
  map<string, int> ans;
  map<string, int> qu;
  queue<int> q;
  q.push(0);
  while (!q.empty()) {
    int cur = q.front();
    q.pop();
    for (int i = 0; i < G[cur].deps.size(); i++) {
      pair<string, int> to = G[cur].deps[i];
      if (ans.find(to.first) != ans.end() || to.first == G[0].name) continue;
      if (qu.find(to.first) != qu.end())
        qu[to.first] = max(qu[to.first], to.second);
      else
        qu.insert(to);
    }
    if (q.empty()) {
      for (auto it : qu) {
        ans.insert(it);
        for (int i = 0; i < n; i++) {
          if (G[i].name == it.first && G[i].version == it.second) {
            q.push(i);
            break;
          }
        }
      }
      qu.clear();
    }
  }
  cout << ans.size() << endl;
  for (auto it : ans) cout << it.first << ' ' << it.second << endl;
  myReturn();
}
