#include <bits/stdc++.h>
using namespace std;
struct edge {
  int from, to;
  int flow, cap;
};
struct DinicFlow {
  vector<edge> edges;
  vector<int> dist, now;
  vector<vector<int> > adj;
  int n, src, snk;
  const int inf = 1e9 + 7;
  DinicFlow() {}
  DinicFlow(int nn) {
    n = nn;
    dist.resize(n);
    now.resize(n);
    adj.resize(n);
  }
  void addEdge(int from, int to, int cap) {
    adj[from].push_back(edges.size());
    edges.push_back({from, to, 0, cap});
    adj[to].push_back(edges.size());
    edges.push_back({to, from, 0, 0});
  }
  bool bfs() {
    for (int i = 0; i < n; ++i) {
      dist[i] = inf;
      now[i] = (int)adj[i].size() - 1;
    }
    queue<int> Q;
    Q.push(src), dist[src] = 0;
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      for (int w : adj[v]) {
        edge& e = edges[w];
        if (dist[e.to] > dist[v] + 1 && e.cap - e.flow > 0) {
          dist[e.to] = dist[v] + 1;
          Q.push(e.to);
        }
      }
    }
    return dist[snk] != inf;
  }
  int dfs(int u, int flow) {
    if (u == snk || !flow) return flow;
    for (int& w = now[u]; w >= 0; --w) {
      edge& e = edges[adj[u][w]];
      if (dist[e.to] == dist[u] + 1 && e.cap > e.flow) {
        int fl = dfs(e.to, min(flow, e.cap - e.flow));
        if (fl > 0) {
          e.flow += fl;
          edges[adj[u][w] ^ 1].flow -= fl;
          return fl;
        }
      }
    }
    return 0;
  }
  int getFlow(int source, int sink) {
    src = source, snk = sink;
    int totFlow = 0;
    int flowLimit = std::numeric_limits<int>::max() >> 2;
    while (bfs()) {
      while (int f = dfs(src, flowLimit)) {
        totFlow += f;
      }
    }
    return totFlow;
  }
};
int main() {
  int n;
  cin >> n;
  vector<vector<int> > sets(n);
  for (int i = 0; i < n; ++i) {
    int m;
    cin >> m;
    for (int j = 0; j < m; ++j) {
      int x;
      cin >> x;
      sets[i].push_back(x - 1);
    }
  }
  vector<int> cost(n);
  int ans = 0;
  for (int i = 0; i < n; ++i) {
    cin >> cost[i];
    cost[i] *= -1;
    ans += max(0, cost[i]);
  }
  DinicFlow df(2 * n + 2);
  for (int i = 0; i < n; ++i) {
    df.addEdge(0, i + 1, 1);
    df.addEdge(i + 1 + n, 2 * n + 1, 1);
    for (int x : sets[i]) df.addEdge(i + 1, x + 1 + n, 1);
  }
  int fl = df.getFlow(0, 2 * n + 1);
  assert(fl == n);
  cerr << "matching = " << fl << "\n";
  vector<int> myMatch(n);
  vector<int> myInvMatch(n);
  for (edge e : df.edges) {
    if (e.flow > 0 && e.from != 0 && e.to != 2 * n + 1) {
      myMatch[e.from - 1] = e.to - 1 - n;
      myInvMatch[e.to - 1 - n] = e.from - 1;
    }
  }
  DinicFlow df1(n + 2);
  for (int i = 0; i < n; ++i) {
    for (int x : sets[i])
      if (x != myMatch[i]) {
        df1.addEdge(i + 1, myInvMatch[x] + 1, 100000000);
      }
  }
  for (int i = 0; i < n; ++i) {
    if (cost[i] > 0)
      df1.addEdge(0, i + 1, cost[i]);
    else
      df1.addEdge(i + 1, n + 1, -cost[i]);
  }
  ans -= df1.getFlow(0, n + 1);
  cout << -ans << "\n";
  return 0;
}
