题意 : 给出二维平面上的两个点代表起点以及终点,接下来给出若干条地铁线路,除了在地铁线路上行进的速度为 40km/h 其余的点到点间都只能用过步行且其速度为 10km/h ,现问你从起点到终点的最短路是多少?
分析 : 这题建完图之后就是裸的最短路了,在建图的时候需要注意地铁的站点之间不能隔点建拥有地铁行进速度的边,也就是若地铁线路为 A->B->C 那么则不能建 A->C 这条速度为 40km/h 的边,因为地铁是在节点间行进的,如果要跨站点那么只能通过步行。图中边的权值为 (两点间距 / 速度 ),其中速度需要将 km/h 转化为 m/min。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #include<ext/pb_ds/priority_queue.hpp> using namespace std; using namespace __gnu_pbds; typedef pair< double, int > pii; const int maxn = 200 + 10; const double INF = 1e30; struct POINT{ int x, y; }; struct EDGE{ int v, nxt; double w; }; double v1, v2; int Head[maxn], cnt, PointCnt; double Dis[maxn]; EDGE Edge[maxn * maxn + maxn]; POINT Point[maxn]; inline void init() { for(int i=0; i<=PointCnt; i++) Head[i] = -1; cnt = 0; PointCnt = 2; } double GetDis(int from, int to) { double x1 = (double)Point[from].x, y1 = (double)Point[from].y; double x2 = (double)Point[to].x, y2 = (double)Point[to].y; return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) ); } inline void AddEdge(int from, int to, bool flag) { double Weight; if(flag) Weight = GetDis(from, to) / v1; else Weight = GetDis(from, to) / v2; Edge[cnt].v = to; Edge[cnt].w = Weight; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } double Dijkstra() { for(int i=1; i<=PointCnt; i++) Dis[i] = INF; __gnu_pbds::priority_queue<pii,greater<pii>,pairing_heap_tag > Heap; Dis[1] = 0.0; Heap.push(make_pair(0.0, 1)); while(!Heap.empty()){ pii T = Heap.top(); Heap.pop(); if(Dis[T.second] != T.first) continue; for(int i=Head[T.second]; i!=-1; i=Edge[i].nxt){ int Eiv = Edge[i].v; if(Dis[Eiv] > Dis[T.second] + Edge[i].w){ Dis[Eiv] = Dis[T.second] + Edge[i].w; Heap.push(make_pair(Dis[Eiv], Eiv)); } } } return Dis[2]; } int main(void) { v1 = 40000.0/60.0; v2 = 10000.0/60.0; PointCnt = maxn - 1; while(~scanf("%d %d", &Point[1].x, &Point[1].y)){ scanf("%d %d", &Point[2].x, &Point[2].y); init(); int x, y; while(scanf("%d %d", &x, &y)!=EOF){ PointCnt++; Point[PointCnt].x = x; Point[PointCnt].y = y; int pre = PointCnt; while(~scanf("%d %d", &x, &y) && !(x==-1 && y==-1)){ PointCnt++; int now = PointCnt; Point[PointCnt].x = x; Point[PointCnt].y = y; AddEdge(pre, now, true); AddEdge(now, pre, true); pre = now; } } for(int i=1; i<=PointCnt; i++){ for(int j=i; j<=PointCnt; j++){ if(j != i){ AddEdge(i, j, false); AddEdge(j, i, false); } } } printf("%.0lf\n", Dijkstra()); } return 0; }