【Week7 作业B】TT的旅行日记
題目描述
眾所周知,TT 有一只魔法貓。
今天他在 B 站上開啟了一次旅行直播,記錄他與魔法貓在喵星旅游時的奇遇。 TT 從家里出發,準備乘坐貓貓快線前往喵星機場。貓貓快線分為經濟線和商業線兩種,它們的速度與價錢都不同。當然啦,商業線要比經濟線貴,TT 平常只能坐經濟線,但是今天 TT 的魔法貓變出了一張商業線車票,可以坐一站商業線。假設 TT 換乘的時間忽略不計,請你幫 TT 找到一條去喵星機場最快的線路,不然就要誤機了!
輸入格式
輸入包含多組數據。每組數據第一行為 3 個整數 N, S 和 E (2 ≤ N ≤ 500, 1 ≤ S, E ≤ 100),即貓貓快線中的車站總數,起點和終點(即喵星機場所在站)編號。
下一行包含一個整數 M (1 ≤ M ≤ 1000),即經濟線的路段條數。
接下來有 M 行,每行 3 個整數 X, Y, Z (1 ≤ X, Y ≤ N, 1 ≤ Z ≤ 100),表示 TT 可以乘坐經濟線在車站 X 和車站 Y 之間往返,其中單程需要 Z 分鐘。
下一行為商業線的路段條數 K (1 ≤ K ≤ 1000)。
接下來 K 行是商業線路段的描述,格式同經濟線。
所有路段都是雙向的,但有可能必須使用商業車票才能到達機場。保證最優解唯一。
輸入樣例
4 1 4 4 1 2 2 1 3 3 2 4 4 3 4 5 1 2 4 3輸出格式
對于每組數據,輸出3行。第一行按訪問順序給出 TT 經過的各個車站(包括起點和終點),第二行是 TT 換乘商業線的車站編號(如果沒有使用商業線車票,輸出"Ticket Not Used",不含引號),第三行是 TT 前往喵星機場花費的總時間。
本題不忽略多余的空格和制表符,且每一組答案間要輸出一個換行
輸出樣例
1 2 4 2 5思路
題中有兩種不同的線路,若沒有商業線,我們可以直接考慮起點到終點的距離。由于商業線的存在,且只能使用一次,所以我們可以枚舉每一條商業線(u,v),其耗時為w,假如我們知道起點到u,v的距離dis1[u],dis1[v]以及終點到u,v的距離dis2[u],dis2[v],取min(dis1[u]+dis2[v]+w,dis1[v]+dis2[u]+w),枚舉完所有商業線后,取得耗時最小的線路,再與不使用商業線的耗時比較,即可取到最小耗時的線路。接下來的問題就是如何求起點到各點,以及終點到各點的最短路。
這里采用Dijkstra算法
Dijkstra
用途
解決圖中無負邊的單源最短路問題。
流程
從源端s出發,dis[a]表示s到a的最短距離,初始化所有dis[a]為無窮大,將s壓入最小堆中,每次從堆中取出距源點最近的點,遍歷該點所連接的邊,更新該點的鄰接點y到源點的距離為min(dis[y],dis[x]+w)(w為邊xy的距離),直到最小堆為空,此時dis數組中即為各點距源點的最短距離。在求取距離的過程中,可通過記錄各點到源點路徑的上一點已達到記錄路徑的目的。
代碼
#include <iostream> #include<queue> #include<string.h> using namespace std; const int size=5e3+10; const int N=500+5; const int inf=1e9; struct Edge{int to,next,w; }e[size]; Edge other[size]; int head[N],tot,n,vis[N],spre[N],sdis[N],tpre[N],tdis[N]; void add(int x,int y,int w) {e[++tot].to=y,e[tot].next=head[x];e[tot].w=w;head[x]=tot; } priority_queue<pair<int,int>>q; void dijkstra(int s,int*dis,int*pre) {while(!q.empty())q.pop();memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++)dis[i]=inf,pre[i]=-1;dis[s]=0;pre[s]=s;q.push(make_pair(0,s));while(!q.empty()){int x=q.top().second;q.pop();if(vis[x])continue;vis[x]=1;for(int i=head[x];i!=-1;i=e[i].next){int y=e[i].to,w=e[i].w;if(dis[y]>dis[x]+w){dis[y]=dis[x]+w;pre[y]=x;q.push(make_pair(-dis[y],y));}}} } void print(int to,int*pre) {if(pre[to]!=to){print(pre[to],pre);printf(" %d",to); }else{printf("%d",to);} } int main(int argc, char** argv) {int s,e;int number=1;while(~scanf("%d%d%d",&n,&s,&e)){if(number!=1)printf("\n");number++;memset(head,-1,sizeof(head));tot=-1;int m;scanf("%d",&m);while(m--){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}int k;scanf("%d",&k);for(int i=0;i<k;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);other[i].next=x,other[i].to=y,other[i].w=z;}dijkstra(s,sdis,spre);dijkstra(e,tdis,tpre);int point=-1,distance=sdis[e];bool sort=true;for(int i=0;i<k;i++){if(sdis[other[i].next]+tdis[other[i].to]+other[i].w<distance){distance=sdis[other[i].next]+tdis[other[i].to]+other[i].w;point=i;sort=true;}if(sdis[other[i].to]+tdis[other[i].next]+other[i].w<distance){distance=sdis[other[i].to]+tdis[other[i].next]+other[i].w;point=i;sort=false;}}if(point==-1){print(e,spre);}else{if(sort){print(other[point].next,spre);int temp=other[point].to;while(tpre[temp]!=temp){printf(" %d",temp);temp=tpre[temp];}printf(" %d",temp);}else{print(other[point].to,spre);int temp=other[point].next;while(tpre[temp]!=temp){printf(" %d",temp);temp=tpre[temp];}printf(" %d",temp);}}printf("\n");if(point==-1)printf("Ticket Not Used\n");else{if(sort)printf("%d\n",other[point].next);elseprintf("%d\n",other[point].to);}printf("%d\n",distance);}return 0; }總結
以上是生活随笔為你收集整理的【Week7 作业B】TT的旅行日记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 课堂经验值管理小程序_小程序刷新课堂评价
- 下一篇: android dbm模式判断,手机信号