int dcmp(double x){ if(fabs(x)<eps)return 0; return x<0?-1:1; } double cross(Vector a,Vector b){ return a.x*b.y-a.y*b.x; } struct Line{ Point p; Vector v; double ang; Line(){} Line(Point p,Vector v):p(p),v(v){ang=atan2(v.y,v.x);} };
bool cmp(const Line& a,const Line& b){ if(dcmp(a.ang-b.ang)==0)return dcmp(cross(a.v,b.p-a.p))<0; return a.ang<b.ang; }
bool onRight(Line L,Point p){ return dcmp(cross(L.v,p-L.p))<=0; }
Point getIntersection(Line a,Line b){ Vector u=a.p-b.p; double t=cross(b.v,u)/cross(a.v,b.v); return a.p+a.v*t; } int n; Line L[N],q[N]; Point p[N]; int main(){ ios::sync_with_stdio(false);cin.tie(0); if(!(cin>>n))return 0; int cnt=0; for(int i=1;i<=n;i++){ int m;cin>>m; vector<Point> poly(m); for(int j=0;j<m;j++)cin>>poly[j].x>>poly[j].y; for(int j=0;j<m;j++)L[++cnt]=Line(poly[j],poly[(j+1)%m]-poly[j]); } sort(L+1,L+cnt+1,cmp); int tot=0; for(int i=1;i<=cnt;i++){ if(i>1&&dcmp(L[i].ang-L[i-1].ang)==0)continue; L[++tot]=L[i]; } int head=1,tail=0; for(int i=1;i<=tot;i++){ while(head<tail&&onRight(L[i],getIntersection(q[tail-1],q[tail])))tail--; while(head<tail&&onRight(L[i],getIntersection(q[head],q[head+1])))head++; q[++tail]=L[i]; if(head<tail&&dcmp(cross(q[tail-1].v,q[tail].v))<=0){ cout<<fixed<<setprecision(3)<<0.000<<"\n"; return 0; } } while(head<tail&&onRight(q[head],getIntersection(q[tail-1],q[tail])))tail--; while(head<tail&&onRight(q[tail],getIntersection(q[head],q[head+1])))head++; if(tail-head+1<3||dcmp(cross(q[tail].v,q[head].v))<=0){ cout<<fixed<<setprecision(3)<<0.000<<"\n"; return 0; } int m=0; for(int i=head;i<tail;i++)p[++m]=getIntersection(q[i],q[i+1]); p[++m]=getIntersection(q[tail],q[head]); double ans=0; for(int i=1;i<=m;i++)ans+=cross(p[i],p[i%m+1]); ans=fabs(ans)/2.0; cout<<fixed<<setprecision(3)<<ans<<"\n"; return 0; }
|