Description
一个凸多边形,任意两点间有连边,有一些边不能使用,求(1)到(n)最短距离,(nleqslant 10^5,mleqslant 10^6)。
Solution
半平面交.
这个路是可以在交点拐上另一条路的..然后就成了几个半平面,按顺序加入可以直接用栈来维护了..
Code
/************************************************************** Problem: 1137 User: BeiYu Language: C++ Result: Accepted Time:6604 ms Memory:74576 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; namespace CG { typedef double LD; const LD eps = 1e-8; #define sqr(x) ((x)*(x)) int dcmp(LD x) { return fabs(x)<eps?0:(x>0?1:-1); } struct Point { LD x,y; Point(LD _x=0,LD _y=0) :x(_x),y(_y) { } }; typedef Point Vector; Vector operator + (const Vector &a,const Vector &b) { return Vector(a.x+b.x,a.y+b.y); } Vector operator - (const Vector &a,const Vector &b) { return Vector(a.x-b.x,a.y-b.y); } Vector operator * (const Vector &a,const LD &b) { return Vector(a.x*b,a.y*b); } LD Cross(const Vector &a,const Vector &b) { return a.x*b.y-a.y*b.x; } LD get_a(const Vector &a) { return atan2(a.y,a.x); } LD dis(const Point &a,const Point &b) { return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } struct Line { Point p; Vector v; LD ang; Line(Point _p=Point(),Vector _v=Vector()) :p(_p),v(_v) { ang=get_a(_v); } Point get_p(LD t) { return p+v*t; } int chkleft(Point pt) { return Cross(v,pt-p)>0; } }; int cmpa(const Line &a,const Line &b) { return a.ang<b.ang; } Point get_l_l(Line a,Line b) { Vector u=a.p-b.p; LD t=Cross(b.v,u)/Cross(a.v,b.v); return a.get_p(t); } } using namespace CG; typedef pair<int,int> pr; const int N = 1e6+50; int n,m; Point p[N]; vector<int> pp[N]; vector<Line> ls; vector<Point> pt; int tp; Line stk[N]; void insert(Line x) { while(tp>=2 && x.chkleft(get_l_l(stk[tp],stk[tp-1]))) tp--; stk[++tp]=x; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int u,v; scanf("%d%d",&u,&v); p[i]=Point(u,v); } for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); if(u>v) swap(u,v); pp[u].push_back(v); } for(int i=1,j,k,t=0;i<=n;i++) { sort(pp[i].begin(),pp[i].end(),greater<int>()); for(j=n,k=0;k<(int)pp[i].size() && j>t;k++,j--) if(pp[i][k]!=j) break; if(j>t) insert(Line(p[i],Point(p[t=j]-p[i]))); } double ans=0; Point lt=p[1],tmp; for(int i=2;i<=tp;i++) tmp=get_l_l(stk[i-1],stk[i]),ans+=dis(lt,tmp),lt=tmp; ans+=dis(lt,p[n]); printf("%.8lf ",ans); return 0; }