#include <bits/stdc++.h>
using namespace std;
const int N = 75010;
struct edge {
  int y, next;
} s[N];
struct loop {
  vector<int> V;
  int S;
} P[N];
struct node {
  int x, y, d;
  bool operator<(const node q) const { return x < q.x; }
};
vector<node> A;
vector<int> F[32768];
int first[N], len = 0, d[N], op[N], low[N], dfn[N], T = 0;
int sta[N], top = 0, totl;
int n, num, D;
map<long long, int> mp;
map<long long, int>::iterator it;
long long sum[20], tot = 0;
void ins(int x, int y) {
  s[++len] = (edge){y, first[x]};
  first[x] = len;
}
void Tarjan(int x) {
  dfn[x] = ++T;
  low[x] = T;
  sta[++top] = x;
  for (int i = first[x]; i != 0; i = s[i].next) {
    if (!dfn[s[i].y]) {
      Tarjan(s[i].y);
      low[x] = min(low[x], low[s[i].y]);
    } else
      low[x] = min(low[x], dfn[s[i].y]);
  }
  if (low[x] == dfn[x]) {
    bool tf = true;
    totl++;
    while (1) {
      int now = sta[top];
      top--;
      P[totl].V.push_back(now);
      if (P[totl].S & (1 << (d[now] - 1))) tf = false;
      P[totl].S |= (1 << (d[now] - 1));
      if (now == x) break;
    }
    if (first[x] == 0 || P[totl].V.size() == 1 && s[first[x]].y != x || !tf)
      return;
    if (!F[P[totl].S].size()) F[P[totl].S].push_back(totl);
  }
}
int main() {
  scanf("%d", &n);
  D = (1 << n) - 1;
  int size = 0, x, y;
  mp.clear();
  for (int i = 1; i <= n; i++) {
    scanf("%d", &size);
    while (size--) {
      num++;
      scanf("%d", &op[num]);
      mp[1ll * op[num]] = num;
      d[num] = i;
      sum[i] += op[num];
    }
    tot += sum[i];
  }
  if (tot % n != 0) {
    printf("No\n");
    return 0;
  }
  tot /= n;
  for (int i = 1; i <= num; i++)
    if (mp[tot - sum[d[i]] + op[i]]) ins(i, mp[tot - sum[d[i]] + op[i]]);
  for (int i = 1; i <= num; i++)
    if (!dfn[i]) Tarjan(i);
  for (int i = 1; i <= D; i++)
    for (int j = i & (i - 1); j; j = (j - 1) & i) {
      if (F[j].size() && F[i ^ j].size()) {
        F[i] = F[i ^ j];
        for (int k = 0; k < F[j].size(); k++) F[i].push_back(F[j][k]);
        break;
      }
    }
  if (!F[D].size())
    printf("No\n");
  else {
    printf("Yes\n");
    for (int i = 0; i < F[D].size(); i++) {
      x = F[D][i];
      for (int j = 0; j < P[x].V.size() - 1; j++)
        A.push_back((node){d[P[x].V[j]], op[P[x].V[j]], d[P[x].V[j + 1]]});
      A.push_back((node){d[P[x].V[P[x].V.size() - 1]],
                         op[P[x].V[P[x].V.size() - 1]], d[P[x].V[0]]});
    }
    sort(A.begin(), A.end());
    for (int i = 0; i < A.size(); i++) printf("%d %d\n", A[i].y, A[i].d);
  }
}
