This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub beet-aizu/library
// verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2454 // verification-helper: ERROR 1e-6 #include<bits/stdc++.h> using namespace std; #define call_from_test #include "../../../geometry/geometry.cpp" #undef call_from_test // segmentArrangement signed main(){ int n,m; cin>>n>>m; vector<Segment> ss(n); Polygon ps(m); for(int i=0;i<n;i++) cin>>ss[i]; for(int i=0;i<m;i++) cin>>ps[i]; map<Point, int> mp; for(int i=0;i<m;i++) mp[ps[i]]=i; Point s,g; cin>>s>>g; ps.emplace_back(s); ps.emplace_back(g); auto H=segmentArrangement(ss,ps); vector< vector< pair<int, double> > > G(H.size()); for(int i=0;i<(int)H.size();i++) for(int j:H[i]) G[i].emplace_back(j,abs(ps[i]-ps[j])); double ans=0,tmp=0; for(int i=0;i<n;i++) ans+=abs(ss[i].p1-ss[i].p2); vector<int> used(G.size(),0); queue<int> q; for(int i=0;i<(int)G.size();i++) if(ps[i]==g) {used[i]=1;q.emplace(i);} while(!q.empty()){ int v=q.front();q.pop(); if(ps[v]==s){ cout<<(int)-1<<endl; return 0; } if(mp.count(ps[v])) continue; for(int u:H[v]){ if(!used[u]){ used[u]=1; q.emplace(u); } } } for(int i=0;i<(int)G.size();i++) if(ps[i]==s) q.emplace(i); while(!q.empty()){ int v=q.front();q.pop(); for(auto &e:G[v]){ int u=e.first; double &c=e.second; if(used[v]&&used[u]) continue; if(c==0) continue; tmp+=c;c=0; q.emplace(u); } } tmp/=2; cout<<fixed<<setprecision(12)<<ans-tmp<<endl; return 0; }
#line 1 "test/aoj/geometry/2454.test.cpp" // verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2454 // verification-helper: ERROR 1e-6 #include<bits/stdc++.h> using namespace std; #define call_from_test #line 1 "geometry/geometry.cpp" #line 3 "geometry/geometry.cpp" using namespace std; #endif //BEGIN CUT HERE #define equals(a,b) (fabs((a)-(b))<EPS) namespace geometry { const double EPS = 1e-10; const double PI = asinl(1) * 2; struct Point{ double x,y; Point(){} Point(double x,double y):x(x),y(y){} Point operator+(Point p) {return Point(x+p.x,y+p.y);} Point operator-(Point p) {return Point(x-p.x,y-p.y);} Point operator*(double k){return Point(x*k,y*k);} Point operator/(double k){return Point(x/k,y/k);} double norm(){return x*x+y*y;} double abs(){return sqrt(norm());} bool operator<(const Point &p) const{ return x!=p.x?x<p.x:y<p.y; //grid-point only //return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0; } bool operator==(const Point &p) const{ return fabs(x-p.x)<EPS and fabs(y-p.y)<EPS; } }; bool sort_x(Point a,Point b){ return a.x!=b.x?a.x<b.x:a.y<b.y; } bool sort_y(Point a,Point b){ return a.y!=b.y?a.y<b.y:a.x<b.x; } typedef Point Vector; typedef vector<Point> Polygon; struct Segment{ Point p1,p2; Segment(){} Segment(Point p1, Point p2):p1(p1),p2(p2){} }; typedef Segment Line; struct Circle{ Point c; double r; Circle(){} Circle(Point c,double r):c(c),r(r){} }; double norm(Vector a){ return a.x*a.x+a.y*a.y; } double abs(Vector a){ return sqrt(norm(a)); } 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; } Point orth(Point p){return Point(-p.y,p.x);} bool isOrthogonal(Vector a,Vector b){ return equals(dot(a,b),0.0); } bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){ return isOrthogonal(a1-a2,b1-b2); } bool isOrthogonal(Segment s1,Segment s2){ return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0); } bool isParallel(Vector a,Vector b){ return equals(cross(a,b),0.0); } bool isParallel(Point a1,Point a2,Point b1,Point b2){ return isParallel(a1-a2,b1-b2); } bool isParallel(Segment s1,Segment s2){ return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0); } Point project(Segment s,Point p){ Vector base=s.p2-s.p1; double r=dot(p-s.p1,base)/norm(base); return s.p1+base*r; } Point reflect(Segment s,Point p){ return p+(project(s,p)-p)*2.0; } double arg(Vector p){ return atan2(p.y,p.x); } Vector polar(double a,double r){ return Point(cos(r)*a,sin(r)*a); } // COUNTER CLOCKWISE static const int CCW_COUNTER_CLOCKWISE = 1; static const int CCW_CLOCKWISE = -1; static const int CCW_ONLINE_BACK = 2; static const int CCW_ONLINE_FRONT = -2; static const int CCW_ON_SEGMENT = 0; int ccw(Point p0,Point p1,Point p2){ Vector a = p1-p0; Vector b = p2-p0; if(cross(a,b) > EPS) return CCW_COUNTER_CLOCKWISE; if(cross(a,b) < -EPS) return CCW_CLOCKWISE; if(dot(a,b) < -EPS) return CCW_ONLINE_BACK; if(a.norm()<b.norm()) return CCW_ONLINE_FRONT; return CCW_ON_SEGMENT; } bool intersectSS(Point p1,Point p2,Point p3,Point p4){ return (ccw(p1,p2,p3)*ccw(p1,p2,p4) <= 0 and ccw(p3,p4,p1)*ccw(p3,p4,p2) <= 0 ); } bool intersectSS(Segment s1,Segment s2){ return intersectSS(s1.p1,s1.p2,s2.p1,s2.p2); } bool intersectPS(Polygon p,Segment l){ int n=p.size(); for(int i=0;i<n;i++) if(intersectSS(Segment(p[i],p[(i+1)%n]),l)) return 1; return 0; } double getDistanceLP(Line l,Point p){ return fabs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1)); } double getDistanceSP(Segment s,Point p){ if(dot(s.p2-s.p1,p-s.p1) < 0.0 ) return abs(p-s.p1); if(dot(s.p1-s.p2,p-s.p2) < 0.0 ) return abs(p-s.p2); return getDistanceLP(s,p); } double getDistanceSS(Segment s1,Segment s2){ if(intersectSS(s1,s2)) return 0.0; return min(min(getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2)), min(getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2))); } // intercsect of circles static const int ICC_SEPERATE = 4; static const int ICC_CIRCUMSCRIBE = 3; static const int ICC_INTERSECT = 2; static const int ICC_INSCRIBE = 1; static const int ICC_CONTAIN = 0; int intersectCC(Circle c1,Circle c2){ if(c1.r<c2.r) swap(c1,c2); double d=abs(c1.c-c2.c); double r=c1.r+c2.r; if(equals(d,r)) return ICC_CIRCUMSCRIBE; if(d>r) return ICC_SEPERATE; if(equals(d+c2.r,c1.r)) return ICC_INSCRIBE; if(d+c2.r<c1.r) return ICC_CONTAIN; return ICC_INTERSECT; } bool intersectSC(Segment s,Circle c){ return getDistanceSP(s,c.c)<=c.r; } int intersectCS(Circle c,Segment s){ if(norm(project(s,c.c)-c.c)-c.r*c.r>EPS) return 0; double d1=abs(c.c-s.p1),d2=abs(c.c-s.p2); if(d1<c.r+EPS and d2<c.r+EPS) return 0; if((d1<c.r-EPS and d2>c.r+EPS) or (d1>c.r+EPS and d2<c.r-EPS)) return 1; Point h=project(s,c.c); if(dot(s.p1-h,s.p2-h)<0) return 2; return 0; } Point getCrossPointSS(Segment s1,Segment s2){ for(int k=0;k<2;k++){ if(getDistanceSP(s1,s2.p1)<EPS) return s2.p1; if(getDistanceSP(s1,s2.p2)<EPS) return s2.p2; swap(s1,s2); } Vector base=s2.p2-s2.p1; double d1=fabs(cross(base,s1.p1-s2.p1)); double d2=fabs(cross(base,s1.p2-s2.p1)); double t=d1/(d1+d2); return s1.p1+(s1.p2-s1.p1)*t; } Point getCrossPointLL(Line l1,Line l2){ double a=cross(l1.p2-l1.p1,l2.p2-l2.p1); double b=cross(l1.p2-l1.p1,l1.p2-l2.p1); if(fabs(a)<EPS and fabs(b)<EPS) return l2.p1; return l2.p1+(l2.p2-l2.p1)*(b/a); } Polygon getCrossPointCL(Circle c,Line l){ Polygon ps; Point pr=project(l,c.c); Vector e=(l.p2-l.p1)/abs(l.p2-l.p1); if(equals(getDistanceLP(l,c.c),c.r)){ ps.emplace_back(pr); return ps; } double base=sqrt(c.r*c.r-norm(pr-c.c)); ps.emplace_back(pr+e*base); ps.emplace_back(pr-e*base); return ps; } Polygon getCrossPointCS(Circle c,Segment s){ Line l(s); Polygon res=getCrossPointCL(c,l); if(intersectCS(c,s)==2) return res; if(res.size()>1u){ if(dot(l.p1-res[0],l.p2-res[0])>0) swap(res[0],res[1]); res.pop_back(); } return res; } Polygon getCrossPointCC(Circle c1,Circle c2){ Polygon p(2); double d=abs(c1.c-c2.c); double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d)); double t=arg(c2.c-c1.c); p[0]=c1.c+polar(c1.r,t+a); p[1]=c1.c+polar(c1.r,t-a); return p; } // IN:2 ON:1 OUT:0 int contains(Polygon g,Point p){ int n=g.size(); bool x=false; for(int i=0;i<n;i++){ Point a=g[i]-p,b=g[(i+1)%n]-p; if(fabs(cross(a,b)) < EPS and dot(a,b) < EPS) return 1; if(a.y>b.y) swap(a,b); if(a.y < EPS and EPS < b.y and cross(a,b) > EPS ) x = !x; } return (x?2:0); } Polygon andrewScan(Polygon s){ Polygon u,l; if(s.size()<3) return s; sort(s.begin(),s.end()); u.push_back(s[0]); u.push_back(s[1]); l.push_back(s[s.size()-1]); l.push_back(s[s.size()-2]); for(int i=2;i<(int)s.size();i++){ for(int n=u.size(); n>=2 and ccw(u[n-2],u[n-1],s[i])!=CCW_CLOCKWISE; n--){ u.pop_back(); } u.push_back(s[i]); } for(int i=s.size()-3;i>=0;i--){ for(int n=l.size(); n>=2 and ccw(l[n-2],l[n-1],s[i])!=CCW_CLOCKWISE; n--){ l.pop_back(); } l.push_back(s[i]); } reverse(l.begin(),l.end()); for(int i=u.size()-2;i>=1;i--) l.push_back(u[i]); return l; } Polygon convex_hull(Polygon ps){ int n=ps.size(); sort(ps.begin(),ps.end(),sort_y); int k=0; Polygon qs(n*2); for(int i=0;i<n;i++){ while(k>1 and cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0) k--; qs[k++]=ps[i]; } for(int i=n-2,t=k;i>=0;i--){ while(k>t and cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0) k--; qs[k++]=ps[i]; } qs.resize(k-1); return qs; } double diameter(Polygon s){ Polygon p=s; int n=p.size(); if(n==2) return abs(p[0]-p[1]); int i=0,j=0; for(int k=0;k<n;k++){ if(p[i]<p[k]) i=k; if(!(p[j]<p[k])) j=k; } double res=0; int si=i,sj=j; while(i!=sj or j!=si){ res=max(res,abs(p[i]-p[j])); if(cross(p[(i+1)%n]-p[i],p[(j+1)%n]-p[j])<0.0){ i=(i+1)%n; }else{ j=(j+1)%n; } } return res; } bool isConvex(Polygon p){ bool f=1; int n=p.size(); for(int i=0;i<n;i++){ int t=ccw(p[(i+n-1)%n],p[i],p[(i+1)%n]); f&=t!=CCW_CLOCKWISE; } return f; } double area(Polygon s){ double res=0; for(int i=0;i<(int)s.size();i++){ res+=cross(s[i],s[(i+1)%s.size()])/2.0; } return res; } double area(Circle c1,Circle c2){ double d=abs(c1.c-c2.c); if(c1.r+c2.r<=d+EPS) return 0; if(d<=fabs(c1.r-c2.r)){ double r=min(c1.r,c2.r); return PI*r*r; } double res=0; for(int k=0;k<2;k++){ double rc=(d*d+c1.r*c1.r-c2.r*c2.r)/(2*d*c1.r); double th=acosl(rc)*2; res+=(th-sinl(th))*c1.r*c1.r/2; swap(c1,c2); } return res; } Polygon convexCut(Polygon p,Line l){ Polygon q; for(int i=0;i<(int)p.size();i++){ Point a=p[i],b=p[(i+1)%p.size()]; if(ccw(l.p1,l.p2,a)!=-1) q.push_back(a); if(ccw(l.p1,l.p2,a)*ccw(l.p1,l.p2,b)<0) q.push_back(getCrossPointLL(Line(a,b),l)); } return q; } Line bisector(Point p1,Point p2){ Circle c1=Circle(p1,abs(p1-p2)),c2=Circle(p2,abs(p1-p2)); Polygon p=getCrossPointCC(c1,c2); if(cross(p2-p1,p[0]-p1)>0) swap(p[0],p[1]); return Line(p[0],p[1]); } Vector translate(Vector v,double theta){ Vector res; res.x=cos(theta)*v.x-sin(theta)*v.y; res.y=sin(theta)*v.x+cos(theta)*v.y; return res; } vector<Line> corner(Line l1,Line l2){ vector<Line> res; if(isParallel(l1,l2)){ double d=getDistanceLP(l1,l2.p1)/2.0; Vector v1=l1.p2-l1.p1; v1=v1/v1.abs()*d; Point p=l2.p1+translate(v1,90.0*(PI/180.0)); double d1=getDistanceLP(l1,p); double d2=getDistanceLP(l2,p); if(fabs(d1-d2)>d){ p=l2.p1+translate(v1,-90.0*(PI/180.0)); } res.push_back(Line(p,p+v1)); }else{ Point p=getCrossPointLL(l1,l2); Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1; v1=v1/v1.abs(); v2=v2/v2.abs(); res.push_back(Line(p,p+(v1+v2))); res.push_back(Line(p,p+translate(v1+v2,90.0*(PI/180.0)))); } return res; } Polygon tangent(Circle c1,Point p2){ Circle c2=Circle(p2,sqrt(norm(c1.c-p2)-c1.r*c1.r)); Polygon p=getCrossPointCC(c1,c2); sort(p.begin(),p.end()); return p; } vector<Line> tangent(Circle c1,Circle c2){ vector<Line> ls; if(c1.r<c2.r) swap(c1,c2); double g=norm(c1.c-c2.c); if(equals(g,0)) return ls; Point u=(c2.c-c1.c)/sqrt(g); Point v=orth(u); for(int s=1;s>=-1;s-=2){ double h=(c1.r+s*c2.r)/sqrt(g); if(equals(1-h*h,0)){ ls.emplace_back(c1.c+u*c1.r,c1.c+(u+v)*c1.r); }else if(1-h*h>0){ Point uu=u*h,vv=v*sqrt(1-h*h); ls.emplace_back(c1.c+(uu+vv)*c1.r,c2.c-(uu+vv)*c2.r*s); ls.emplace_back(c1.c+(uu-vv)*c1.r,c2.c-(uu-vv)*c2.r*s); } } return ls; } double closest_pair(Polygon &a,int l=0,int r=-1){ if(r<0){ r=a.size(); sort(a.begin(),a.end(),sort_x); } if(r-l<=1) return abs(a[0]-a[1]); int m=(l+r)>>1; double x=a[m].x; double d=min(closest_pair(a,l,m),closest_pair(a,m,r)); inplace_merge(a.begin()+l,a.begin()+m,a.begin()+r,sort_y); Polygon b; for(int i=l;i<r;i++){ if(fabs(a[i].x-x)>=d) continue; for(int j=0;j<(int)b.size();j++){ double dy=a[i].y-next(b.rbegin(),j)->y; if(dy>=d) break; d=min(d,abs(a[i]-*next(b.rbegin(),j))); } b.emplace_back(a[i]); } return d; } vector<vector<int>> segmentArrangement(vector<Segment> &ss, Polygon &ps){ int n=ss.size(); for(int i=0;i<n;i++){ ps.emplace_back(ss[i].p1); ps.emplace_back(ss[i].p2); for(int j=i+1;j<n;j++) if(intersectSS(ss[i],ss[j])) ps.emplace_back(getCrossPointSS(ss[i],ss[j])); } sort(ps.begin(),ps.end()); ps.erase(unique(ps.begin(),ps.end()),ps.end()); vector<vector<int> > G(ps.size()); for(int i=0;i<n;i++){ vector<pair<double,int> > ls; for(int j=0;j<(int)ps.size();j++) if(getDistanceSP(ss[i],ps[j])<EPS) ls.emplace_back(make_pair(norm(ss[i].p1-ps[j]),j)); sort(ls.begin(),ls.end()); for(int j=0;j+1<(int)ls.size();j++){ int a=ls[j].second,b=ls[j+1].second; G[a].emplace_back(b); G[b].emplace_back(a); } } for(auto &v:G){ sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); } return G; } struct EndPoint{ Point p; int seg,st; EndPoint(){} EndPoint(Point p,int seg,int st):p(p),seg(seg),st(st){} bool operator<(const EndPoint &ep)const{ if(p.y==ep.p.y) return st<ep.st; return p.y<ep.p.y; } }; int manhattan_intersection(vector<Segment> ss,const int INF){ const int BTM = 0; const int LFT = 1; const int RGH = 2; const int TOP = 3; int n=ss.size(); vector<EndPoint> ep; for(int i=0;i<n;i++){ if(ss[i].p1.y==ss[i].p2.y){ if(ss[i].p1.x>ss[i].p2.x) swap(ss[i].p1,ss[i].p2); ep.emplace_back(ss[i].p1,i,LFT); ep.emplace_back(ss[i].p2,i,RGH); }else{ if(ss[i].p1.y>ss[i].p2.y) swap(ss[i].p1,ss[i].p2); ep.emplace_back(ss[i].p1,i,BTM); ep.emplace_back(ss[i].p2,i,TOP); } } sort(ep.begin(),ep.end()); set<int> bt; bt.insert(INF); int cnt=0; for(int i=0;i<n*2;i++){ if(ep[i].st==TOP){ bt.erase(ep[i].p.x); }else if(ep[i].st==BTM){ bt.emplace(ep[i].p.x); }else if(ep[i].st==LFT){ auto b=bt.lower_bound(ss[ep[i].seg].p1.x); auto e=bt.upper_bound(ss[ep[i].seg].p2.x); cnt+=distance(b,e); } } return cnt; } double area(Polygon ps,Circle c){ if(ps.size()<3u) return 0; function<double(Circle, Point, Point)> dfs= [&](Circle c,Point a,Point b){ Vector va=c.c-a,vb=c.c-b; double f=cross(va,vb),res=0; if(equals(f,0.0)) return res; if(max(abs(va),abs(vb))<c.r+EPS) return f; Vector d(dot(va,vb),cross(va,vb)); if(getDistanceSP(Segment(a,b),c.c)>c.r-EPS) return c.r*c.r*atan2(d.y,d.x); auto u=getCrossPointCS(c,Segment(a,b)); if(u.empty()) return res; if(u.size()>1u and dot(u[1]-u[0],a-u[0])>0) swap(u[0],u[1]); u.emplace(u.begin(),a); u.emplace_back(b); for(int i=1;i<(int)u.size();i++) res+=dfs(c,u[i-1],u[i]); return res; }; double res=0; for(int i=0;i<(int)ps.size();i++) res+=dfs(c,ps[i],ps[(i+1)%ps.size()]); return res/2; } } using namespace geometry; namespace geometry{ istream &operator>>(istream &is,Point &p){ is>>p.x>>p.y; return is; } istream &operator>>(istream &is,Polygon &p){ for(int i=0;i<(int)p.size();i++) is>>p[i]; return is; } istream &operator>>(istream &is,Segment &s){ is>>s.p1>>s.p2; return is; } istream &operator>>(istream &is,Circle &c){ is>>c.c>>c.r; return is; } ostream &operator<<(ostream &os,Point p){ os<<fixed<<setprecision(12)<<p.x<<" "<<p.y; return os; } } //END CUT HERE #ifndef call_from_test signed main(){ return 0; } #endif #line 9 "test/aoj/geometry/2454.test.cpp" #undef call_from_test // segmentArrangement signed main(){ int n,m; cin>>n>>m; vector<Segment> ss(n); Polygon ps(m); for(int i=0;i<n;i++) cin>>ss[i]; for(int i=0;i<m;i++) cin>>ps[i]; map<Point, int> mp; for(int i=0;i<m;i++) mp[ps[i]]=i; Point s,g; cin>>s>>g; ps.emplace_back(s); ps.emplace_back(g); auto H=segmentArrangement(ss,ps); vector< vector< pair<int, double> > > G(H.size()); for(int i=0;i<(int)H.size();i++) for(int j:H[i]) G[i].emplace_back(j,abs(ps[i]-ps[j])); double ans=0,tmp=0; for(int i=0;i<n;i++) ans+=abs(ss[i].p1-ss[i].p2); vector<int> used(G.size(),0); queue<int> q; for(int i=0;i<(int)G.size();i++) if(ps[i]==g) {used[i]=1;q.emplace(i);} while(!q.empty()){ int v=q.front();q.pop(); if(ps[v]==s){ cout<<(int)-1<<endl; return 0; } if(mp.count(ps[v])) continue; for(int u:H[v]){ if(!used[u]){ used[u]=1; q.emplace(u); } } } for(int i=0;i<(int)G.size();i++) if(ps[i]==s) q.emplace(i); while(!q.empty()){ int v=q.front();q.pop(); for(auto &e:G[v]){ int u=e.first; double &c=e.second; if(used[v]&&used[u]) continue; if(c==0) continue; tmp+=c;c=0; q.emplace(u); } } tmp/=2; cout<<fixed<<setprecision(12)<<ans-tmp<<endl; return 0; }