题目
因为可以在相交线段上换乘。所以容易想到答案就是包含1-n这条边的内部不包含边的凸包的周长。
发现对于每个点,只有标号最大的邻接点有用。
然后半平面交即可。
再也不敢用map了,
1
0
6
10^6
106直接卡到TLE,换了vector+sort直接B站第一页
AC Code:
#include<bits/stdc++.h>
#define maxn 100005
#define eps 1e-6
using namespace std;
int n,m;
vector<int>G[maxn];
double sqr(double a){ return a*a; }
struct Point{
double x,y;
inline Point(double x=0,double y=0):x(x),y(y){}
inline Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
inline Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
inline double operator *(const Point &B)const{ return x*B.y-y*B.x; }
inline Point operator *(const double &B)const{ return Point(x*B,y*B); }
inline double dist(const Point &B)const{ return sqrt(sqr(x-B.x)+sqr(y-B.y)); }
}P[maxn];
struct Line{
Point A,B;
double ag;
}L[maxn*2];int tot;
int id[maxn*2];
inline int sgn(double a){ return a<-eps?-1:a>eps?1:0; }
inline bool inLeft(const Point &P,const Point &A,const Point &B){
return (B-A) * (P-A) > 0;
}
inline bool cmp(const int &u,const int &v){
if(sgn(L[u].ag-L[v].ag)) return L[u].ag < L[v].ag;
return inLeft(L[u].A,L[v].A,L[v].B);
}
inline Point Ipt(const Point &p1,const Point &p2,const Point &p3,const Point &p4){
Point u = p2 - p1 , v = p4 - p3 , w = p2 - p4;
return p2 + (p1 - p2) * ((w * v) / (u * v));
}
int qL[maxn*2],l,r;
Point qp[maxn*2];
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &res){
char ch;bool f = 0;
for(;!isdigit(ch=getc());) if(ch=='-') f=1;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
(f) && (res = -res);
}
int main(){
read(n),read(m);
for(int i=1;i<=n;i++) read(P[i].x),read(P[i].y);
for(int i=1;i<=m;i++){
int x,y;
read(x),read(y);
if(x > y) swap(x,y);
G[x].push_back(y);
}
for(int i=1;i<=n;i++){
int j;
sort(G[i].begin(),G[i].end());
int k = G[i].size() - 1;
for(j=n;k>=0&&j>=i&&G[i][k]==j;j--,k--);
if(j>i){
L[++tot].A = P[j] , L[tot].B = P[i];
L[tot].ag = atan2(P[i].y-P[j].y,P[i].x-P[j].x);
id[tot] = tot;
}
}
L[++tot].A=P[1],L[tot].B=P[n];
L[tot].ag = atan2(P[n].y-P[1].y,P[n].x-P[1].x);
id[tot] = tot;
sort(id+1,id+1+tot,cmp);
qL[r++] = id[1];
for(int i=2,u;i<=tot;i++)
if(sgn(L[u=id[i]].ag - L[id[i-1]].ag)){
for(;r-l>=2 && !inLeft(qp[r-2],L[u].A,L[u].B);r--);
for(;r-l>=2 && !inLeft(qp[l],L[u].A,L[u].B);l++);
qL[r++] = u;
if(r-l>=2)
qp[r-2] = Ipt(L[qL[r-2]].A,L[qL[r-2]].B,L[u].A,L[u].B);
}
//for(;r-l>=2 && !inLeft(qp[l],L[qL[r-1]].A,L[qL[r-1]].B);l++);
for(;r-l>=2 && !inLeft(qp[r-2],L[qL[l]].A,L[qL[l]].B);r--);
if(r-l <= 2) printf("%.10lf\n",P[1].dist(P[n]));
else
{
qp[r-1] = Ipt(L[qL[l]].A,L[qL[l]].B,L[qL[r-1]].A,L[qL[r-1]].B);
double ans = 0;
qp[r] = qp[l];
for(int i=l;i<=r-1;i++)
ans += qp[i+1].dist(qp[i]);
printf("%.10lf\n",ans-P[1].dist(P[n]));
}
}