#include <bits/stdc++.h>
using namespace std;
const long double EPS = 1e-9;
const long double pi = acos(-1);
struct point {
  long double x, y;
};
point operator+(const point &a, const point &b) {
  return {a.x + b.x, a.y + b.y};
}
point operator-(const point &a, const point &b) {
  return {a.x - b.x, a.y - b.y};
}
point operator*(const long double &k, const point &p) {
  return {p.x * k, p.y * k};
}
point operator/(const point &p, const long double &k) {
  return {p.x / k, p.y / k};
}
long double calc_ang(const point &a) {
  long double ang = atan2(a.y, a.x);
  if (ang < 0.0) {
    return ang + 2 * pi;
  }
  return ang;
}
long double dot(const point &a, const point &b) {
  return a.x * b.x + a.y * b.y;
}
long double norm_sq(const point &a) { return dot(a, a); }
long double cross(const point &a, const point &b) {
  return a.x * b.y - a.y * b.x;
}
struct line {
  point a, b;
  int idx;
};
long double offset(const line &l) { return cross(l.b - l.a, l.a); }
point intersection(const line &l1, const line &l2) {
  return (offset(l1) * (l2.b - l2.a) - offset(l2) * (l1.b - l1.a)) /
         cross(l1.b - l1.a, l2.b - l2.a);
}
point intersection(const line &l, const long double &ang) {
  return intersection({{0, 0}, {cos(ang), sin(ang)}}, l);
}
void add_segment(point a, point b, vector<line> &segments) {
  if (abs(cross(a, b)) < EPS) {
    return;
  }
  if (cross(a, b) < 0.0) {
    swap(a, b);
  }
  if (a.y < 0.0 && b.y > 0.0) {
    point tmp = intersection({{0, 0}, {1, 0}}, {a, b});
    add_segment(a, tmp, segments);
    add_segment(tmp, b, segments);
  } else {
    if (a.y < 0.0 && abs(b.y) < EPS) {
      b.y = -EPS;
    }
    segments.push_back({a, b, (int)segments.size()});
  }
}
struct node {
  int i, j;
  line l1, l2;
};
long double cur_ang;
vector<line> segments;
struct comp {
  bool operator()(const int &a, const int &b) const {
    double tmp_a = norm_sq(intersection(segments[a], cur_ang));
    double tmp_b = norm_sq(intersection(segments[b], cur_ang));
    if (abs(tmp_a - tmp_b) < EPS) {
      return a < b;
    }
    return tmp_a < tmp_b;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int c;
    cin >> c;
    vector<point> polygon(c);
    for (int i = 0; i < c; i++) {
      cin >> polygon[i].x >> polygon[i].y;
    }
    for (int i = 0; i < c; i++) {
      add_segment(polygon[i], polygon[(i + 1) % c], segments);
    }
  }
  vector<long double> a;
  for (auto &seg : segments) {
    a.push_back(calc_ang(seg.a));
    a.push_back(calc_ang(seg.b));
  }
  sort(a.begin(), a.end());
  a.erase(unique(a.begin(), a.end()), a.end());
  a.push_back(2 * pi);
  vector<vector<int> > add((int)a.size()), remove((int)a.size());
  for (auto &seg : segments) {
    int l = upper_bound(a.begin(), a.end(), calc_ang(seg.a)) - a.begin() - 1;
    int r = upper_bound(a.begin(), a.end(), calc_ang(seg.b)) - a.begin() - 1;
    add[l].push_back(seg.idx);
    remove[r].push_back(seg.idx);
  }
  set<int, comp> st;
  long double ans = 0;
  for (int i = 0; i < (int)a.size() - 1; i++) {
    cur_ang = a[i] + EPS;
    for (auto &x : add[i]) {
      st.insert(x);
    }
    for (auto &x : remove[i]) {
      st.erase(x);
    }
    if ((int)st.size() >= 2) {
      line l1 = segments[*st.begin()], l2 = segments[*next(st.begin())];
      point v = intersection(l1, a[i]), w = intersection(l1, a[i + 1]);
      vector<point> tmp = {v, w};
      ans -= cross(v, w);
      v = intersection(l2, a[i]), w = intersection(l2, a[i + 1]);
      tmp.push_back(w);
      tmp.push_back(v);
      ans += cross(v, w);
    }
  }
  cout << fixed << setprecision(10) << ans / 2.0 << '\n';
  return 0;
}
