#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
string to_string(pair<A, B> p);
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);
string to_string(const string& s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string)s); }
string to_string(bool b) { return (b ? "true" : "false"); }
string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}
template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}
template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto& x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ")";
}
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
const int MAXN = (int)1e6 + 10;
int main() {
  ios_base::sync_with_stdio(false), cin.tie(nullptr);
  int boxes;
  cin >> boxes;
  vector<vector<int> > a(boxes);
  vector<vector<int> > visited(boxes);
  int64_t S = 0;
  for (int i = 0; i < boxes; i++) {
    int n;
    cin >> n;
    vector<int> weights(n);
    for (int& w : weights) {
      cin >> w;
      S += w;
    }
    a[i] = weights;
    visited[i] = vector<int>(n, 0);
  }
  if (S % boxes != 0) {
    cout << "No"
         << "\n";
    return 0;
  }
  S /= boxes;
  vector<int64_t> d;
  for (auto box : a) {
    int64_t w = 0;
    for (int box_weight : box) {
      w += box_weight;
    }
    d.push_back(S - w);
  }
  42;
  map<int64_t, pair<int, int> > where;
  for (int i = 0; i < boxes; i++) {
    for (int j = 0; j < a[i].size(); j++) {
      where[a[i][j]] = {i, j};
    }
  }
  map<int, vector<pair<int, int> > > cycleItemsMap;
  set<int> goodMasks;
  for (int i = 0; i < boxes; i++) {
    for (int j = 0; j < a[i].size(); j++) {
      int x = i, y = j;
      int mask = 0;
      int cycle = true;
      vector<pair<int, int> > markedVisited;
      vector<pair<int, int> > cycleItems;
      set<int> rowsTaken;
      while (true) {
        if (visited[x][y]) {
          if (x != i && y != j) {
            cycle = false;
          }
          break;
        }
        if (rowsTaken.count(x)) {
          cycle = false;
          break;
        }
        rowsTaken.insert(x);
        mask |= (1 << x);
        visited[x][y] = true;
        cycleItems.push_back({x, y});
        markedVisited.push_back({x, y});
        if (where.count(a[x][y] + d[x])) {
          auto it = where[a[x][y] + d[x]];
          x = it.first;
          y = it.second;
        } else {
          cycle = false;
          break;
        }
      }
      if (cycle && goodMasks.count(mask) == 0) {
        42;
        cycleItemsMap[mask] = cycleItems;
        goodMasks.insert(mask);
      }
      for (auto p : markedVisited) {
        visited[p.first][p.second] = false;
      }
    }
  }
  42;
  vector<int> previous(1 << boxes, -1);
  for (int mask : goodMasks) {
    previous[mask] = 0;
  }
  for (int mask = 1; mask < (1 << boxes); mask++) {
    for (int s = mask; s > 0; s = (s - 1) & mask) {
      if (s == mask) {
        continue;
      }
      if (cycleItemsMap.count(s) && previous[s ^ mask] != -1) {
        previous[mask] = s ^ mask;
        break;
      }
    }
  }
  if (previous[(1 << boxes) - 1] == -1) {
    cout << "No"
         << "\n";
    return 0;
  }
  int mask = (1 << boxes) - 1;
  vector<pair<int, int> > answer(boxes);
  while (mask > 0) {
    int nextMask = previous[mask];
    assert(nextMask != -1);
    int cycleMask = mask ^ nextMask;
    assert(cycleItemsMap.count(cycleMask));
    auto positions = cycleItemsMap[cycleMask];
    vector<int> vals;
    for (auto pos : positions) {
      vals.push_back(a[pos.first][pos.second]);
    }
    for (int i = 0; i < positions.size(); i++) {
      answer[positions[i].first] = {
          a[positions[i].first][positions[i].second],
          positions[(i - 1 + (int)positions.size()) % (int)positions.size()]
              .first};
    }
    mask = nextMask;
  }
  cout << "Yes"
       << "\n";
  for (int i = 0; i < boxes; i++) {
    cout << answer[i].first << " " << answer[i].second + 1 << "\n";
  }
  return 0;
}
