#include <bits/stdc++.h>
using namespace std;
const long long oo = 1e18;
const long long MAXN = 16;
long long K;
map<long long, long long> mp;
map<long long, bool> have;
map<long long, bool> mark;
map<long long, bool> mk;
map<long long, long long> idx;
vector<long long> A[MAXN];
long long dif[MAXN];
long long dp[1 << MAXN];
long long best[1 << MAXN];
struct st {
  long long u, v, w;
};
vector<st> rdp[1 << MAXN];
pair<long long, long long> sol[MAXN];
void DFS(long long nodo) {
  if (!best[nodo]) {
    for (auto x : rdp[nodo]) {
      sol[x.u] = {x.w, x.v + 1};
    }
    return;
  } else {
    DFS(best[nodo]);
    DFS(best[nodo] ^ nodo);
  }
}
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> K;
  long long sum = 0;
  for (long long i = 0; i < K; i++) {
    long long N;
    cin >> N;
    for (long long j = 0; j < N; j++) {
      long long n;
      cin >> n;
      mark[n] = true;
      idx[n] = i;
      A[i].push_back(n);
      sum += n;
    }
  }
  if (sum % K) {
    cout << "NO" << '\n';
    return 0;
  }
  sum /= K;
  for (long long i = 0; i < K; i++) {
    long long ss = 0;
    for (long long j = 0; j < A[i].size(); j++) {
      ss += A[i][j];
    }
    dif[i] = sum - ss;
  }
  for (long long i = 0; i < K; i++) {
    for (long long j = 0; j < A[i].size(); j++) {
      long long temp = A[i][j] + dif[i];
      if ((mark[temp] && idx[temp] != i) || (!dif[i])) {
        mp[A[i][j]] = temp;
        have[A[i][j]] = true;
      }
    }
  }
  for (auto x : mark) {
    if (!x.second) continue;
    long long pt = x.first;
    if (!mk[pt]) {
      map<long long, bool> temp;
      vector<long long> vect;
      bool flag = true;
      while (!mk[pt]) {
        temp[pt] = true;
        mk[pt] = true;
        vect.push_back(pt);
        if (have[pt])
          pt = mp[pt];
        else {
          flag = false;
          break;
        }
      }
      if (temp[pt] && flag) {
        long long mask = 0;
        bool correct = true;
        vector<st> tt;
        while (vect.back() != pt) {
          if (mask & (1 << idx[vect.back()])) correct = false;
          mask |= (1 << idx[vect.back()]);
          tt.push_back({idx[vect.back()], 0, vect.back()});
          vect.pop_back();
        }
        if (mask & (1 << idx[vect.back()])) correct = false;
        mask |= (1 << idx[vect.back()]);
        tt.push_back({idx[vect.back()], 0, vect.back()});
        if (correct) {
          for (long long i = 0; i < tt.size(); i++) {
            if (i + 1 != tt.size())
              tt[i].v = tt[i + 1].u;
            else
              tt[i].v = tt[0].u;
          }
          rdp[mask] = tt;
          dp[mask] = true;
        }
      }
    }
  }
  for (long long i = 0; i < (1 << K); i++) {
    for (long long j = (i - 1) & i; j != 0; j = (j - 1) & i) {
      if (!dp[i] && (dp[j] & dp[i ^ j])) {
        dp[i] = true;
        best[i] = j;
      }
    }
  }
  if (dp[(1 << K) - 1]) {
    cout << "YES" << '\n';
    DFS((1 << K) - 1);
    for (long long i = 0; i < K; i++) {
      cout << sol[i].first << " " << sol[i].second << '\n';
    }
  } else
    cout << "NO" << '\n';
  return 0;
}
