UVA 1048 - Low Cost Air Travel
\(\mathsf{\color{Thistle}{Statement}}\)
给定 \(n\) 张机票和 \(q\) 次旅行,每张机票都给出飞机所经过的城市,每一次乘座飞机,必须从飞机的起始站开始,且中途不能乘坐其他飞机再回来乘坐该架飞机,但是可以提前离开飞机。
对于第 \(i\) 次旅行,输出一次经过给定城市所需的最小代价。
\(\mathsf{\color{Thistle}{Solution}}\)
如果计算相邻 \(2\) 个城市之间的最小花费并累计,显然是不对的,因为可能相邻 \(3\) 个城市在一条航程上。
故,考虑 \((i,j)\) 表示走过了前 \(i\) 个给定城市,当前位于 \(j\)。那么,以该二元组建图后,再跑最短路即可。对于 \((i,j)\) 这个点,枚举可能所在的航道,以及在该航道飞至第几个城市,对于所有可能连边建图即可。
举个例子:「样例 \(1\)」\((1,1)\rightarrow (2,3),(1,1)\rightarrow (2,4),(1,1)\rightarrow (1,2)\dots\)
这样,对于 \(1\) 条边,其实便等价于 \(1\) 次换乘,所以边权也是显而易见的,时间复杂度:\(O(qn^4l)\),其中 \(l\) 为查询路径的长度。
注意:输出方案的时候,末尾不能有多余的空格✨。
\(\mathsf{\color{Thistle}{Code}}\)
#include <bits/stdc++.h>
#define fi first
#define se second
#define int long long
using namespace std;
typedef pair<int, int> PII;
typedef pair<int, PII> PIII;
typedef long long LL;
const int N = 25;
int n, q, l;
struct route {
int w;
std::vector<int> city;
}rt[N];
std::map<PII, vector<PIII>> g;
std::map<PII, int> st;
std::map<PII, pair<PII, PII>> dist;
void dijkstra(PII start) {
priority_queue<PIII, vector<PIII>, greater<PIII>> heap;
dist.clear(), st.clear(), heap.push({0, start}), dist[start] = {{0, 0}, start};
while (heap.size()) {
auto u = heap.top();
heap.pop();
if (st.count(u.se)) continue;
st[u.se] = 1;
for (auto v : g[u.se]) {
heap.push({u.fi + rt[v.fi].w, v.se});
if (!dist.count(v.se)) dist[v.se] = {{u.fi + rt[v.fi].w, v.fi}, u.se};
else if (u.fi + rt[v.fi].w < dist[v.se].fi.fi) dist[v.se] = {{u.fi + rt[v.fi].w, v.fi}, u.se};
}
}
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int cs = 0;
while (cin >> n && n) {
set<int> pnt;
for (int i = 1; i <= n; i ++) {
cin >> rt[i].w >> l, rt[i].city.resize(l + 1);
for (int j = 1; j <= l; j ++)
cin >> rt[i].city[j], pnt.insert(rt[i].city[j]);
}
cin >> q, cs ++;
for (int trip = 1; trip <= q; trip ++) {
cin >> l;
std::vector<int> path(l + 1);
for (int i = 1; i <= l; i ++)
cin >> path[i];
for (int i = 1; i < l; i ++)
for (auto v : pnt) {
for (int j = 1; j <= n; j ++)
if (rt[j].city[1] == v) {
int tmp = i;
for (int k = 2; k < rt[j].city.size(); k ++) {
if (tmp < l && rt[j].city[k] == path[tmp + 1]) tmp ++;
g[{i, v}].push_back({j, {tmp, rt[j].city[k]}});
}
}
}
dijkstra({1, path[1]});
cout << "Case " << cs << ", Trip " << trip << ": Cost = " << dist[{l, path[l]}].fi.fi << endl;
PII End = {l, path[l]};
std::vector<int> way;
while (End != make_pair(1ll, path[1])) {
way.push_back(dist[End].fi.se);
End = dist[End].se;
}
reverse(way.begin(), way.end());
cout << " Tickets used: ";
for (int i = 0; i < way.size(); i ++) {
if (i == way.size() - 1) cout << way[i];
else cout << way[i] << " ";
}
cout << endl;
g.clear();
}
}
return 0;
}
标签:rt,dist,int,精讲,1048,Air,heap,fi,se
From: https://www.cnblogs.com/Tiny-konnyaku/p/18256229