UVA Airport Express
题意:在Iokh市机场快线分为经济线和商业线。线路和速度价格都不同。你只有一张商业线车票,即最多只能坐一站商业线,其他时候只能坐经济线。找出一条去机场最快的线路。
思路:因为商业线只能坐一站,假如乘坐一条商业线(a,b),那么起点到a,b到终点都必须是最短路。所以先预处理起点和终点到其他所有点的最短路,分别记为f()和g(),两次dijstra即可。那么我们只需枚举每条商业线求出所有的f(a)+T(a,b)+g(b)然后求最小即可。
1w是TLE,改成了优先队列优化的dijstra,白书上的模板。
2w是RE,题目中说边数最多1000条,开到1010仍然re,果断开到10010。
#include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include <string.h> #include <queue> #define LL long long #define _LL __int64 using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 510; const int maxm = 10100; struct node { int u,v,w,next; }edge[maxm]; int cnt,head[maxm]; int n,m,k; int s,t; int dis_s[maxm],dis_t[maxm]; int pre_s[maxm],pre_t[maxm]; int ans; int path[maxm]; void init() { cnt = 0; memset(head,-1,sizeof(head)); } void add(int u, int v, int w) { edge[cnt] = ((struct node){u,v,w,head[u]}); head[u] = cnt++; } void dijstra(int u) { int dis[maxn],pre[maxn]; priority_queue <pair<int,int>,vector<pair<int,int> >, greater<pair<int,int> > > que; bool vis[maxn]; memset(vis,false,sizeof(vis)); for(int i = 1; i <= n; i++) { dis[i] = (i == u ? 0 : INF); } que.push(make_pair(dis[u],u)); pre[u] = -1; while(!que.empty()) { pair<int,int> p = que.top(); que.pop(); int v = p.second; if(vis[v]) continue; vis[v] = true; for(int i = head[v]; i != -1; i = edge[i].next) { if( dis[edge[i].v] > dis[v] + edge[i].w) { dis[edge[i].v] = dis[v] + edge[i].w; pre[edge[i].v] = v; que.push(make_pair(dis[edge[i].v],edge[i].v)); } } } if(u == s) { memcpy(dis_s,dis,sizeof(dis)); memcpy(pre_s,pre,sizeof(pre)); } if(u == t) { memcpy(dis_t,dis,sizeof(dis)); memcpy(pre_t,pre,sizeof(pre)); } } void solve() { int mid_u,mid_v,u,v,w; int flag = 0; int cnt,tmp; scanf("%d",&k); for(int i = 0; i < k; i++) { scanf("%d %d %d",&u,&v,&w); if(dis_s[u] + dis_t[v] + w < ans) { ans = dis_s[u] + dis_t[v] + w; mid_u = u; mid_v = v; flag = 1; } if(dis_s[v] + dis_t[u] + w < ans) { ans = dis_s[v] + dis_t[u] + w; mid_u = v; mid_v = u; flag = 1; } } if(flag == 0) { cnt = 0; tmp = t; path[cnt++] = tmp; while( pre_s[tmp] != -1) { path[cnt++] = pre_s[tmp]; tmp = pre_s[tmp]; } for(int i = cnt-1; i > 0; i--) printf("%d ",path[i]); printf("%d\n",path[0]); printf("Ticket Not Used\n"); } else { cnt = 0; tmp = mid_u; path[cnt++] = tmp; while(pre_s[tmp] != -1) { path[cnt++] = pre_s[tmp]; tmp = pre_s[tmp]; } for(int i = cnt-1; i >= 0; i--) printf("%d ",path[i]); cnt = 0; tmp = mid_v; path[cnt++] = tmp; while(pre_t[tmp] != -1) { path[cnt++] = pre_t[tmp]; tmp = pre_t[tmp]; } for(int i = 0; i < cnt-1; i++) printf("%d ",path[i]); printf("%d\n",path[cnt-1]); printf("%d\n",mid_u); } printf("%d\n",ans); } int main() { int item = 0; while(~scanf("%d %d %d",&n,&s,&t)) { if(item) printf("\n"); init(); int u,v,w; scanf("%d",&m); for(int i = 0; i < m; i++) { scanf("%d %d %d",&u,&v,&w); add(u,v,w); add(v,u,w); } dijstra(s); //预处理 dijstra(t); ans = dis_s[t]; solve(); item++; } return 0; }