Problem: Problem

You were asked by a company to create a program. The company has $ N $ jobs, and each job is numbered from $ 1 $ to $ N $. There are $ M_i $ prerequisite jobs $ X_ {i, j} $ in job $ i $, and work $ X_ {i, j} $ is performed before job $ X_ {i, j} $. And work $ i $ suffers a great loss.

So ask you to find the number of jobs you lost when you did all the jobs in the order that minimized the number of jobs you lost.

Constraints

The input satisfies the following conditions.

* $ 1 \ le N \ le 10 ^ 5 $
* $ 0 \ le M_i \ le N $
* Sum of $ M_i $ does not exceed $ 10 ^ 5 $
* $ 1 \ le X_ {i, j} \ le min (i + 1, N) $

Input

All inputs are given as integers in the following format:


$ N $
$ M_1 $ $ X_ {1,1} $ $ X_ {1,2} $ ... $ X_ {1, M_1} $
$ M_2 $ $ X_ {2,1} $ $ X_ {2,2} $ ... $ X_ {2, M_2} ​​$
::
$ M_N $ $ X_ {N, 1} $ $ X_ {N, 2} $ ... $ X_ {N, M_N} $


The number of jobs $ N $ is given to the $ 1 $ line.
The following $ N $ line gives information on the prerequisite work. Information on work $ i $ is given on the $ i + 1 $ line, separated by blanks. $ M_i $ represents the number of jobs that are the premise of work $ i $, and $ X_ {i, j} $ is the number of jobs that are the premise of job $ i $.

Output

When all the jobs are done in the order that minimizes the number of jobs incurred, the number of jobs incurred at that time is output in one line.

Examples

Input

2
1 1
0


Output

1


Input

3
3 2 1 2
0
1 2


Output

1


Input

5
1 2
1 3
2 1 2
3 1 3 5
0


Output

1

Solution (in CPP):

Solution:
#include <bits/stdc++.h>

using namespace std;

using namespace std;
using Int = long long;

//BEGIN CUT HERE
template< typename T >
struct MonotoneMinima {
  using F = function< T(int, int) >;
  int n;
  F dist;
  T INF;
  vector< T > dp;

  // dist(i,l) + dist(j,k) >= dist(i,k) + dist(j,l)
  // if( i<=j && k<=l )
  MonotoneMinima(int n, F dist, T INF) :
      n(n), dist(dist), INF(INF), dp(n + 1, INF) {}

  void dfs(int l, int r, int a, int b) {
    if(l == r) return;
    int m = (l + r) >> 1;
    T ma = INF;
    int mi = -1;
    for(int i = a; i < b; i++) {
      T tmp = dp[i + 1] + dist(i, m);
      if(tmp < ma) ma = tmp, mi = i;
    }
    dp[m] = min(dp[m], ma);
    dfs(l, m, a, mi + 1);
    dfs(m + 1, r, mi, b);
  }

  void solve(int l, int r) {
    if(l + 1 == r) {
      dp[l] = min(dp[l], dp[r] + dist(l, l));
      return;
    }
    int m = (l + r) >> 1;
    solve(m, r);
    dfs(l, m, m, r);
    solve(l, m);
  }

  T solve() {
    dp[n] = 0;
    solve(0, n);
    return dp[0];
  }
};

struct SuccinctIndexableDictionary {
  size_t length;
  size_t blocks;
  vector< unsigned > bit, sum;

  SuccinctIndexableDictionary() {
  }

  SuccinctIndexableDictionary(size_t _length) {
    length = _length;
    blocks = (length + 31) >> 5;
    bit.assign(blocks, 0U);
    sum.assign(blocks, 0U);
  }

  void set(int k) {
    bit[k >> 5] |= 1U << (k & 31);
  }

  void build() {
    sum[0] = 0U;
    for(int i = 1; i < blocks; i++) {
      sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]);
    }
  }

  bool operator[](int k) const {
    return (bool((bit[k >> 5] >> (k & 31)) & 1));
  }

  int rank(int k) {
    return (sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1)));
  }

  int rank(bool val, int k) {
    return (val ? rank(k) : k - rank(k));
  }

  int select(bool val, int k) {
    if(k < 0 || rank(val, length) <= k) return (-1);
    int low = 0, high = length;
    while(high - low > 1) {
      int mid = (low + high) >> 1;
      if(rank(val, mid) >= k + 1) high = mid;
      else low = mid;
    }
    return (high - 1);
  }

  int select(bool val, int i, int l) {
    return select(val, i + rank(val, l));
  }
};

template< class T, int MAXLOG >
struct WaveletMatrix {
  size_t length;
  SuccinctIndexableDictionary matrix[MAXLOG];
  int zs[MAXLOG];
  int buff1[MAXLOG], buff2[MAXLOG];

  void max_dfs(int d, int l, int r, int &k, T val, vector< T > &vs) {
    if(l >= r || !k) return;
    if(d == MAXLOG) {
      while(l++ < r && k > 0) vs.push_back(val), k--;
      return;
    }
    int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
    max_dfs(d + 1, lc + zs[d], rc + zs[d], k, 1ULL << (MAXLOG - d - 1) | val, vs);
    max_dfs(d + 1, l - lc, r - rc, k, val, vs);
  }

  T max_dfs(int d, int l, int r, T val, T a, T b) {
    if(r - l <= 0 || val >= b) return -1;
    if(d == MAXLOG) return val >= a ? val : -1;
    int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
    T ret = max_dfs(d + 1, lc + zs[d], rc + zs[d], 1ULL << (MAXLOG - d - 1) | val, a, b);
    if(~ret) return ret;
    return max_dfs(d + 1, l - lc, r - rc, val, a, b);
  }

  int freq_dfs(int d, int l, int r, T val, T a, T b) {
    if(l == r) return 0;
    if(d == MAXLOG) return (a <= val && val < b) ? r - l : 0;
    T nv = 1ULL << (MAXLOG - d - 1) | val, nnv = ((1ULL << (MAXLOG - d - 1)) - 1) | nv;
    if(nnv < a || b <= val) return 0;
    if(a <= val && nnv < b) return r - l;
    int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
    return freq_dfs(d + 1, l - lc, r - rc, val, a, b) +
           freq_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b);
  }

  void list_dfs(int d, int l, int r, T val, T a, T b, vector< pair< T, int>> &vs) {
    if(val >= b || r - l <= 0) return;
    if(d == MAXLOG) {
      if(a <= val) vs.push_back(make_pair(val, r - l));
      return;
    }
    T nv = val | (1LL << (MAXLOG - d - 1)), nnv = nv | (((1LL << (MAXLOG - d - 1)) - 1));
    if(nnv < a) return;
    int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
    list_dfs(d + 1, l - lc, r - rc, val, a, b, vs);
    list_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b, vs);
  }


  WaveletMatrix(vector< T > data) {
    length = data.size();
    vector< T > l(length), r(length);
    for(int depth = 0; depth < MAXLOG; depth++) {
      matrix[depth] = SuccinctIndexableDictionary(length + 1);
      int left = 0, right = 0;
      for(int i = 0; i < length; i++) {
        bool k = (data[i] >> (MAXLOG - depth - 1)) & 1;
        if(k) r[right++] = data[i], matrix[depth].set(i);
        else l[left++] = data[i];
      }
      zs[depth] = left;
      matrix[depth].build();
      swap(l, data);
      for(int i = 0; i < right; i++) data[left + i] = r[i];
    }
  }

  T access(int k) {
    int ret = 0;
    bool bit;
    for(int depth = 0; depth < MAXLOG; depth++) {
      bit = matrix[depth][k];
      ret = (ret << 1) | bit;
      k = matrix[depth].rank(bit, k) + zs[depth] * bit;
    }
    return (ret);
  }

  int rank(T val, int k) {
    int l = 0, r = k;
    for(int depth = 0; depth < MAXLOG; depth++) {
      buff1[depth] = l, buff2[depth] = r;
      bool bit = (val >> (MAXLOG - depth - 1)) & 1;
      l = matrix[depth].rank(bit, l) + zs[depth] * bit;
      r = matrix[depth].rank(bit, r) + zs[depth] * bit;
    }
    return (r - l);
  }

  int select(T val, int kth) {
    rank(val, length);
    for(int depth = MAXLOG - 1; depth >= 0; depth--) {
      bool bit = (val >> (MAXLOG - depth - 1)) & 1;
      kth = matrix[depth].select(bit, kth, buff1[depth]);
      if(kth >= buff2[depth] || kth < 0) return (-1);
      kth -= buff1[depth];
    }
    return (kth);
  }

  int select(T val, int k, int l) {
    return (select(val, k + rank(val, l)));
  }


  int quantile(int left, int right, int kth) {
    if(right - left <= kth || kth < 0) return (-1);
    T ret = 0;
    for(int depth = 0; depth < MAXLOG; depth++) {
      int l = matrix[depth].rank(1, left);
      int r = matrix[depth].rank(1, right);
      if(r - l > kth) {
        left = l + zs[depth];
        right = r + zs[depth];
        ret |= 1ULL << (MAXLOG - depth - 1);
      } else {
        kth -= r - l;
        left -= l;
        right -= r;
      }
    }
    return (ret);
  }

  vector< T > topk(int l, int r, int k) {
    if(r - l < k) k = r - l;
    if(k < 0) return (vector< T >());
    vector< T > ret;
    max_dfs(0, l, r, k, 0, ret);
    return (ret);
  }

  vector< pair< T, int > > freq_list(int l, int r, T a, T b) {
    vector< pair< T, int > > ret;
    list_dfs(0, l, r, 0, a, b, ret);
    return (ret);
  }

  vector< pair< int, T > > get_rect(int l, int r, T a, T b) {
    vector< pair< T, int > > res = freq_list(l, r, a, b);
    vector< pair< int, T > > ret;
    for(auto &e : res) {
      for(int i = 0; i < e.second; i++) {
        ret.emplace_back(select(e.first, i, l), e.first);
      }
    }
    return (ret);
  }

  int rangefreq(int left, int right, T lower, T upper) {
    return (freq_dfs(0, left, right, 0, lower, upper));
  }
};


int main() {
  int N;
  vector< int > g[100000];
  bool nxt[100000] = {};


  cin >> N;
  for(int i = 0; i < N; i++) {
    int x;
    cin >> x;
    bool flag = false;
    while(x--) {
      int v;
      cin >> v;
      --v;
      if(v == i + 1) nxt[i] = true;
      else g[i].emplace_back(v);
    }
  }
  vector< int > near(N);
  for(int i = 0; i < N; i++) {
    sort(begin(g[i]), end(g[i]));
    near[i] = 0;
    if(g[i].size()) near[i] = g[i].back() + 1;
  }
  WaveletMatrix< int, 19 > mat(near);

  auto dist = [&](int r, int l) {
    int cost = nxt[r] | near[r] - 1 >= l;
    cost += mat.rangefreq(l, r, l + 1, N + 5);
    return cost;
  };
  using int64 = long long;
  const int64 INF = 1LL << 60;
  MonotoneMinima< int64 > beet(N, dist, INF);
  cout << beet.solve() << endl;
}