#include <bits/stdc++.h>
using namespace std;
const int maxn = 200005;
const double inf = 0x3f3f3f3f;
const double eps = 1e-6;
const double pi = acos(-1);
int n, tot, sz;
double ang[maxn];
struct node {
  double x, y;
  node(double x_ = 0, double y_ = 0) : x(x_), y(y_) {}
  inline double len() { return sqrt(x * x + y * y); }
} p[maxn];
inline node operator+(const node &a, const node &b) {
  return node(a.x + b.x, a.y + b.y);
}
inline node operator-(const node &a, const node &b) {
  return node(a.x - b.x, a.y - b.y);
}
inline node operator*(const node &a, const double &b) {
  return node(a.x * b, a.y * b);
}
inline node operator/(const node &a, const double &b) {
  return node(a.x / b, a.y / b);
}
inline double dot(const node &a, const node &b) {
  return a.x * b.x + a.y * b.y;
}
inline double cross(const node &a, const node &b) {
  return a.x * b.y - a.y * b.x;
}
struct line {
  node x, y;
  double ra, rb;
  line(node x_ = node(), node y_ = node(), double ra_ = -pi, double rb_ = -pi)
      : x(x_), y(y_), ra(ra_), rb(rb_) {}
} A[maxn];
inline node intersection(line a, line b) {
  return a.x + ((a.y - a.x) *
                (cross(b.y - b.x, a.x - b.x) / cross(a.y - a.x, b.y - b.x)));
}
inline node get(line a, double rad) {
  return intersection(a, line(node(0, 0), node(cos(rad), sin(rad))));
}
inline bool better(line a, line b, double rad) {
  if (fabs(a.ra - a.rb) < eps) return 0;
  if (fabs(b.ra - b.rb) < eps) return 1;
  node A = get(a, rad), B = get(b, rad);
  return A.len() < B.len();
}
struct Segment_Tree {
  struct node {
    line fi, se;
    double rad;
  } t[maxn << 2];
  int n;
  void build(int rt, int l, int r) {
    t[rt].rad = (ang[l] + ang[r + 1]) / 2;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build((rt << 1), l, mid), build((rt << 1 | 1), mid + 1, r);
  }
  inline void init(int n_) { n = n_, build(1, 1, n); }
  inline void addline(int rt, line a) {
    if (better(a, t[rt].fi, t[rt].rad))
      t[rt].se = t[rt].fi, t[rt].fi = a;
    else if (better(a, t[rt].se, t[rt].rad))
      t[rt].se = a;
  }
  inline void pushdown(int rt) {
    if (t[rt].fi.ra != t[rt].fi.rb)
      addline((rt << 1), t[rt].fi), addline((rt << 1 | 1), t[rt].fi);
    if (t[rt].se.ra != t[rt].se.rb)
      addline((rt << 1), t[rt].se), addline((rt << 1 | 1), t[rt].se);
  }
  void update(int rt, int l, int r, int x, int y, line a) {
    if (x <= l && r <= y) {
      addline(rt, a);
      return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) update((rt << 1), l, mid, x, y, a);
    if (y > mid) update((rt << 1 | 1), mid + 1, r, x, y, a);
  }
  inline void update(int l, int r, line &a) { update(1, 1, n, l, r, a); }
  double res;
  void getans(int rt, int l, int r) {
    if (l == r) {
      if (t[rt].fi.ra == t[rt].fi.rb) return;
      res += cross(get(t[rt].se, ang[l]), get(t[rt].se, ang[r + 1]));
      res -= cross(get(t[rt].fi, ang[l]), get(t[rt].fi, ang[r + 1]));
      return;
    }
    pushdown(rt);
    int mid = (l + r) >> 1;
    getans((rt << 1), l, mid), getans((rt << 1 | 1), mid + 1, r);
  }
  inline double getans() {
    getans(1, 1, n);
    return res / 2;
  }
} T;
inline void addsegment(node a, node b) {
  if (fabs(cross(a, b)) < eps) return;
  if (cross(a, b) < -eps) swap(a, b);
  if (a.y > eps && b.y < -eps) {
    node p = intersection(line(a, b), line(node(0, 0), node(-inf, 0)));
    p.y = 0, addsegment(a, p), addsegment(b, p);
  } else {
    double ra = atan2(a.y, a.x), rb = atan2(b.y, b.x);
    if (ra > rb) ra = -pi;
    A[++tot] = line(a, b, ra, rb);
  }
}
int main() {
  int Case;
  scanf("%d", &Case);
  while (Case--) {
    int m;
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
    p[m + 1] = p[1];
    for (int i = 1; i <= m; i++) addsegment(p[i], p[i + 1]);
  }
  for (int i = 1; i <= tot; i++) ang[++sz] = A[i].ra, ang[++sz] = A[i].rb;
  sort(ang + 1, ang + sz + 1);
  int sz_ = sz;
  sz = 0;
  for (int i = 1; i <= sz_; i++)
    if (i == 1 || ang[i] - ang[sz] > eps) ang[++sz] = ang[i];
  T.init(sz - 1);
  for (int i = 1; i <= tot; i++) {
    int l = lower_bound(ang + 1, ang + sz + 1, A[i].ra - eps) - ang;
    int r = lower_bound(ang + 1, ang + sz + 1, A[i].rb - eps) - ang - 1;
    T.update(l, r, A[i]);
  }
  printf("%.10lf\n", T.getans());
  return 0;
}
