![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const long double eps=1e-8; const double pi=acos(-1.0); int sgn(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } int dcmp(double x,double y) { if(fabs(x-y)<eps) return 0; return x<y?-1:1; } struct Point { double x,y; Point() {}; Point(double x,double y):x(x),y(y) {} Point operator + (Point b) { return Point(x+b.x,y+b.y); } Point operator -(Point b) { return Point(x-b.x,y-b.y); } Point operator *(double k) { return Point(x*k,y*k); } Point operator /(double k) { return Point(x/k,y/k); } bool operator ==(Point b) { return sgn(x-b.x)==0&&sgn(y-b.y)==0; } bool operator <(Point b) { return sgn(x-b.x)<0||(sgn(x-b.x)==0&&sgn(y-b.y)<0); } } now[1000],nex[1000],over[1000],res[1000]; typedef Point Vector; double dot(Vector A,Vector B) { //点积 return A.x*B.x+A.y*B.y; } double Cross(Vector a,Vector b) { //叉积 return a.x*b.y-a.y*b.x; } bool cmp(Point r,Point t) { //极角排序 Point tt=t-res[0]; Point rr=r-res[0]; if(sgn(Cross(rr,tt))==0) return (rr.x*rr.x+rr.y*rr.y)<(tt.x*tt.x+tt.y*tt.y); return sgn(Cross(rr,tt))>0; } Struct Line { Point P1, P2; Line () {}; Line (Point P1, Point P2): P1 (P1), P2 (P2) {} }; typedef Line segment; BOOL Point_on_seg (Point P, Line V) { / / relationship between point and line segment, the segment 0 is a point, a line segment point for the return SGN (Cross (pv.p1, v.p2-v.p1)) == 0 && SGN (dOT (pv.p1, PV .p2)) <= 0 ; } Point Cross_Point (Point a, Point B, Point C, Point D) { // two line focus of Double S1 = Cross (BA, the C- a); Double S2 = Cross (BA , D- A); return Point (CX DX-S2 * S1 *, Dy * CY * S1-S2) / (S1-S2); // must first determined whether the two parallel or coincident } BOOLcross_segment (Point A, Point B, Point C, Point D) { Double C1 = Cross (BA, CA), C2 = Cross (BA, D- A); Double D1 = Cross (DC, AC), D2 = Cross ( DC, B- C); return SGN (C1) * SGN (C2) < 0 && SGN (D1) * SGN (D2) < 0 ; // . 1 intersects disjoint 0 } BOOL Point_in_polygon (Point Pt, Point P *, int n-) { // . 1 inside the polygon represents 0 or outside the boundary for ( int I = 0 ; I <n-; I ++ ) { IF (P [I] == Pt) return . 1 ; } for ( int i=0; i<n; i++) { Line v=Line(p[i],p[(i+1)%n]); if(Point_on_seg(pt,v)) return 1; } int num=0; for(int i=0; i<n; i++) { int j=(i+1)%n; int c=sgn(Cross(pt-p[j],p[i]-p[j])); int u=sgn(p[i].y-pt.y); int v=sgn(p[j].y-pt.y); if(c>0&&u<0&&v>=0) num++; if(c<0&&u>=0&&v<0) num--; } return num!=0; } int main() { // freopen("in.txt","r",stdin); int t; scanf("%d",&t); int lenow; for(int i=1; i<=t; i++) { int n; scanf("%d",&n); for(int j=0; j<n; j++) { scanf("%lf%lf",&nex[j].x,&nex[j].y); } // res[0]=nex[0]; //sort(nex,nex+n,cmp); if(i==1) { for(int j=0; j<n; j++) { now[j]=nex[j]; } lenow=n; } else { int cnt=0; for(int j=0; j<lenow; j++) { for(int w=0; w<n; w++) { if(cross_segment(now[j],now[(j+1)%lenow],nex[w],nex[(w+1)%n])) { over[cnt++]=Cross_Point(now[j],now[(j+1)%lenow],nex[w],nex[(w+1)%n]); //cout<<now[j].x<<" "<<now[j].y<<" "<<now[(j+1)%lenow].x<<" "<<now[(j+1)%lenow].y<<" "; // cout<<nex[w].x<<" "<<nex[w].y<<" "<<nex[(w+1)%n].x<<" "<<nex[(w+1)%n].y<<" "<<over[cnt-1].x<<" "<<over[cnt-1].y<<" "<<endl; } } } int tot=0; for(int j=0; j<lenow; j++) { if(Point_in_polygon(now[j],nex,n)&&Point_in_polygon(now[j],now,lenow)) { //cout<<"*"<<now[j].x<<" "<<now[j].y<<endl; res[tot++]=now[j]; } } for(int j=0; j<n; j++) { if(Point_in_polygon(nex[j],nex,n)&&Point_in_polygon(nex[j],now,lenow)) { // cout<<"**"<<nex[j].x<<" "<<nex[j].y<<endl; res[tot++]=nex[j]; } } for(int j=0; j<cnt; j++) { if(Point_in_polygon(over[j],nex,n)&&Point_in_polygon(over[j],now,lenow)) { // cout<<"***"<<over[j].x<<" "<<over[j].y<<endl; res[tot++]=over[j]; } } if(tot<=2) { printf("0.000\n"); return 0; } else { sort(res+1,res+tot,cmp); for(int j=0; j<tot; j++) { now[j]=res[j]; //cout<<now[j].x<<" "<<now[j].y<<endl; } lenow=tot; } } // scanf("%d",) } double ans=0; for(int i=0; i<lenow; i++) { //cout<<now[i].x<<" "<<now[i].y<<" "<<ans<<endl; ans+=Cross(now[i],now[(i+1)%lenow]); } printf("%.3f\n",0.5*ans); return 0; }