考虑将所有交点作为关键点来建图跑最短路,但图上的关键点数量最坏为$o(nm)$,需要优化
当$s=0$且$g=n-1$的部分分,有以下结论:
1.对于一段天桥$([l,r],y)$,不会从$(r,y)$向左移动到$(l,y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)$更优
2.对于一座天桥$([l,r],y)$,不会从竖直方向经过$(l',y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)=>(l',y)$更优
3.对于一座天桥$([l,r],y)$,不会从$(x,y)$向下移动,否则必然会再经过$(x',y)$或$(r,y')$,前者根据结论2一定不优,后者不如$(x,y)=>(r,y)=>(r,y')$更优
对于一座天桥$([l,r],y)$,其中$(x,y)$为关键点当且仅当$x=l$或$x=r$或其向上走经过的第一个交点为天桥端点,那么点数最多为$3m$,即解决了$s=0$且$t=n-1$的部分分
那么对于原题,先不妨假设$s<g$,那么对于一座天桥$([l,r],y)$,其要特殊考虑当且仅当$l<s$或$g<r$,以$l<s$为例:找到$s$左边/右边(包括$s$)第一个能上桥的点$a$和$b$($h_{a,b}ge y$),那么将整座桥拆成$([l,a],y)$,$([a,b],y)$和$([b,r],y)$即可
View Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define oo 1e15 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 #define pii pair<int,int> 9 #define mp make_pair 10 #define fi first 11 #define se second 12 struct ji{ 13 int nex,to,len; 14 }edge[N*80]; 15 struct build{ 16 int x,h; 17 }bu[N]; 18 struct bridge{ 19 int l,r,y; 20 bool operator < (const bridge &k)const{ 21 return (y<k.y)||(y==k.y)&&(l<k.l); 22 } 23 }br[N*5]; 24 priority_queue<pair<long long,int> >q; 25 map<pii,int>mat; 26 vector<pii>v; 27 int V,E,n,m,s,t,f[N<<2],head[N*20],vis[N*20]; 28 long long ans,d[N*20]; 29 bool cmp(pii x,pii y){ 30 return (x.se<y.se)||(x.se==y.se)&&(x.fi<y.fi); 31 } 32 void build(int k,int l,int r){ 33 if (l==r){ 34 f[k]=bu[l].h; 35 return; 36 } 37 build(L,l,mid); 38 build(R,mid+1,r); 39 f[k]=max(f[L],f[R]); 40 } 41 int find1(int k,int l,int r,int x,int y,int z){ 42 if ((l>y)||(x>r)||(f[k]<z))return 0; 43 if (l==r)return l; 44 int a=find1(R,mid+1,r,x,y,z); 45 if (a)return a; 46 return find1(L,l,mid,x,y,z); 47 } 48 int find2(int k,int l,int r,int x,int y,int z){ 49 if ((l>y)||(x>r)||(f[k]<z))return 0; 50 if (l==r)return l; 51 int a=find2(L,l,mid,x,y,z); 52 if (a)return a; 53 return find2(R,mid+1,r,x,y,z); 54 } 55 void update(int k,int l,int r,int x,int y,int z){ 56 if ((l>y)||(x>r))return; 57 if ((x<=l)&&(r<=y)){ 58 f[k]=max(f[k],z); 59 return; 60 } 61 update(L,l,mid,x,y,z); 62 update(R,mid+1,r,x,y,z); 63 } 64 int query(int k,int l,int r,int x){ 65 if (l==r)return f[k]; 66 if (x<=mid)return max(f[k],query(L,l,mid,x)); 67 return max(f[k],query(R,mid+1,r,x)); 68 } 69 void add(int x,int y,int z){ 70 edge[E].nex=head[x]; 71 edge[E].to=y; 72 edge[E].len=z; 73 head[x]=E++; 74 } 75 void split(int k,int x){ 76 if ((x)&&(br[k].l<x)&&(x<br[k].r)){ 77 br[++m]=bridge{br[k].l,x,br[k].y}; 78 br[k].l=x; 79 } 80 } 81 void split(){ 82 build(1,1,n); 83 for(int i=1;i<=m;i++){ 84 int a,b; 85 if (br[i].l<s){ 86 split(i,find1(1,1,n,1,s,br[i].y)); 87 split(i,find2(1,1,n,s,n,br[i].y)); 88 } 89 if (t<br[i].r){ 90 split(i,find1(1,1,n,1,t,br[i].y)); 91 split(i,find2(1,1,n,t,n,br[i].y)); 92 } 93 } 94 } 95 void build(){ 96 memset(head,-1,sizeof(head)); 97 sort(v.begin(),v.end()); 98 for(int i=0;i<v.size();i++) 99 if ((!i)||(v[i-1]!=v[i]))mat[v[i]]=++V; 100 for(int i=0,j=0;i<v.size();i=++j) 101 for(;((j<v.size())&&(v[j].fi==v[j+1].fi));j++) 102 if (v[j].se!=v[j+1].se){ 103 add(mat[v[j]],mat[v[j+1]],v[j+1].se-v[j].se); 104 add(mat[v[j+1]],mat[v[j]],v[j+1].se-v[j].se); 105 } 106 sort(v.begin(),v.end(),cmp); 107 for(int i=1,j=0;i<=m;i++){ 108 while ((br[i].y!=v[j].se)||(br[i].l!=v[j].fi))j++; 109 for(;((br[i].y!=v[j].se)||(br[i].r!=v[j].fi));j++) 110 if (v[j].fi!=v[j+1].fi){ 111 add(mat[v[j]],mat[v[j+1]],bu[v[j+1].fi].x-bu[v[j].fi].x); 112 add(mat[v[j+1]],mat[v[j]],bu[v[j+1].fi].x-bu[v[j].fi].x); 113 } 114 } 115 } 116 long long dij(int s,int t){ 117 memset(vis,0,sizeof(vis)); 118 for(int i=1;i<=V;i++)d[i]=oo; 119 d[s]=0; 120 q.push(mp(0,s)); 121 while (!q.empty()){ 122 int k=q.top().se; 123 q.pop(); 124 if (vis[k])continue; 125 vis[k]=1; 126 for(int i=head[k];i!=-1;i=edge[i].nex) 127 if (d[edge[i].to]>d[k]+edge[i].len){ 128 d[edge[i].to]=d[k]+edge[i].len; 129 q.push(mp(-d[edge[i].to],edge[i].to)); 130 } 131 } 132 return d[t]; 133 } 134 int main(){ 135 scanf("%d%d",&n,&m); 136 for(int i=1;i<=n;i++)scanf("%d%d",&bu[i].x,&bu[i].h); 137 for(int i=1;i<=m;i++){ 138 scanf("%d%d%d",&br[i].l,&br[i].r,&br[i].y); 139 br[i].l++,br[i].r++; 140 } 141 scanf("%d%d",&s,&t); 142 s++,t++; 143 if (s>t)swap(s,t); 144 v.push_back(mp(s,0)); 145 v.push_back(mp(t,0)); 146 split(); 147 sort(br+1,br+m+1); 148 memset(f,0,sizeof(f)); 149 for(int i=1,j=1;i<=m;i++){ 150 if (br[j].y<br[i].y) 151 for(;j<i;j++)update(1,1,n,br[j].l,br[j].r,br[j].y); 152 v.push_back(mp(br[i].l,br[i].y)); 153 v.push_back(mp(br[i].r,br[i].y)); 154 v.push_back(mp(br[i].l,query(1,1,n,br[i].l))); 155 v.push_back(mp(br[i].r,query(1,1,n,br[i].r))); 156 } 157 build(); 158 ans=dij(mat[mp(s,0)],mat[mp(t,0)]); 159 if (ans==oo)ans=-1; 160 printf("%lld",ans); 161 }