BZOJ 1137: [POI2009]Wsp 岛屿
Description
一个凸多边形,任意两点间有连边,有一些边不能使用,求\(1\)到\(n\)最短距离,\(n\leqslant 10^5,m\leqslant 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\n",ans);
return 0;
}

浙公网安备 33010602011771号