生活随笔
收集整理的這篇文章主要介紹了
Week7 B - TT 的旅行日记
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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 行是商業線路段的描述,格式同經濟線。
所有路段都是雙向的,但有可能必須使用商業車票才能到達機場。保證最優解唯一。
輸出
對于每組數據,輸出3行。第一行按訪問順序給出 TT 經過的各個車站(包括起點和終點),第二行是 TT 換乘商業線的車站編號(如果沒有使用商業線車票,輸出"Ticket Not Used",不含引號),第三行是 TT 前往喵星機場花費的總時間。
本題不忽略多余的空格和制表符,且每一組答案間要輸出一個換行
輸入樣例
4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3
輸出樣例
1 2 4
2
5
解題思路
利用 dijkstra 算法求單原(權值)最短路徑
但是本題有一張免費的車票
要從起點遍歷一遍 求每個點到起點的距離 及最短路程
再從終點遍歷一遍 求每個點到終點的距離 及最短路程
兩路程分別為倒序即正序
遍歷可使用車票的額外站點
從額外站點的出發站往起點遍歷路程 因為出發站不一定在原先最短路程上
若從起點開始找可能會找不到 所以要倒敘查找路程
再從額外站點的到達站往終點遍歷路程
若用了車票并沒有比較快就不要用然后把票賣了
并直接輸出正序或倒序都可以
Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
const int inf
=5*1e8;
const int maxnu
=2500;
using namespace std
;
int n
,s
,e
;
int m
,k
;
struct Edge
{int to
=0;int next
=0;int v
=0;
}edge
[maxnu
];
int head
[maxnu
];
int tot
;
int dis
[3][maxnu
];
int vis
[maxnu
];
int fro
[3][maxnu
];
void add(int x
,int y
,int v
){edge
[++tot
].to
=y
;edge
[tot
].next
=head
[x
];edge
[tot
].v
=v
;head
[x
]=tot
;
}
priority_queue
<pair
<int , int > >q
;
void dijkstra(int s
,int z
,int r
){while(q
.size()) q
.pop();memset(vis
,0,sizeof(vis
));for(int i
=1;i
<=n
;i
++){dis
[z
][i
]=inf
;}dis
[z
][s
]=0;fro
[r
][s
]=-1;q
.push(make_pair(0,s
));while(q
.size()){int x
=q
.top().second
;q
.pop();if(vis
[x
])continue;vis
[x
]=1;for(int i
=head
[x
];i
;i
=edge
[i
].next
){int y
=edge
[i
].to
,v
=edge
[i
].v
;if(dis
[z
][y
]>dis
[z
][x
]+v
){dis
[z
][y
]=dis
[z
][x
]+v
;fro
[r
][edge
[i
].to
]=x
;q
.push(make_pair(-dis
[z
][y
],y
));}}}
}
void output(int x
,int y
){while(x
!=y
&&x
!=0){cout
<<x
<<' ';x
=fro
[1][x
]; }cout
<<x
;return;
}
void output2(int x
,int y
){if(x
==y
){printf("%d",y
);return;}if(fro
[0][y
]==0){printf("%d",y
);return;}if(fro
[0][y
]==x
){printf("%d %d",x
,y
);return;}else{output2(x
,fro
[0][y
]);printf(" %d",y
);}
}
int main(){int a
,b
,w
;int ti
=0;
while(scanf("%d %d %d",&n
,&s
,&e
)!=EOF){cin
>>m
;while(m
--){scanf("%d %d %d",&a
,&b
,&w
);add(a
,b
,w
);add(b
,a
,w
);}dijkstra(s
,0,0);dijkstra(e
,1,1);int ansdis
=inf
;int st
=0,ste
=0; cin
>>k
;int dis1
,dis2
;while(k
--){scanf("%d %d %d",&a
,&b
,&w
);dis1
=dis
[0][a
]+dis
[1][b
]+w
;dis2
=dis
[0][b
]+dis
[1][a
]+w
;if(ansdis
>dis1
){ansdis
=dis1
;st
=a
;ste
=b
;}if(ansdis
>dis2
){ansdis
=dis2
;st
=b
;ste
=a
;}}if(ti
>0)cout
<<endl
;ti
++;if(ansdis
>dis
[0][e
]){output(s
,e
);cout
<<endl
;cout
<<"Ticket Not Used"<<endl
;cout
<<dis
[0][e
]<<endl
;}else{output2(s
,st
);cout
<<' ';output(ste
,e
);cout
<<endl
;cout
<<st
<<endl
;cout
<<ansdis
<<endl
;}for(int i
=0;i
<m
;i
++){fro
[0][i
]=0;fro
[1][i
]=0;}memset(head
,0,sizeof(head
));tot
=0;
}
}
總結
以上是生活随笔為你收集整理的Week7 B - TT 的旅行日记的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。