五、完善程序-1
第一题:特殊最短路(最多一条免费边)
给定一个含N个点、M条边的带权无向图,边权非负。起点为S,终点为T。对于一条S到T的路径,可以在整条路径中至多选择一条边作为“免费边”:当第一次经过这条被选中的边时,费用视为0;如果之后再次经过该边,则仍按其原始权重计费(点和边均允许重复经过)。求从S到T的最小总费用。
以下代码求解了上述问题,试补全程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #include <algorithm> #include <iostream> #include <queue> #include <vector> using namespace std; const long long INF = 1e18; struct Edge { int to; int weight; }; struct State { long long dist; int u; int used_freebie; bool operator>(const State &other) const { return dist > other.dist; } }; int main() { int n, m, s, t; cin >> n >> m >> s >> t; vector<vector<Edge>> adj(n + 1); for (int i = 0; i < m; ++i) { int u, v, w; cin >> u >> v >> w; adj[u].push_back({v, w}); adj[v].push_back({u, w}); } vector<vector<long long>> d(n + 1, vector<long long>(2, INF)); priority_queue<State, vector<State>, greater<State>> pq; d[s][0] = 0; pq.push({0, s, ①}); while (!pq.empty()) { State current = pq.top(); pq.pop(); long long dist = current.dist; int u = current.u; int used = current.used_freebie; if (dist > ②) { continue; } for (const auto &edge : adj[u]) { int v = edge.to; int w = edge.weight; if (d[u][used] + w < ③) { ③ = d[u][used] + w; pq.push({③, v, used}); } if (used == 0) { if (④ < d[v][1]) { d[v][1] = ④; pq.push({d[v][1], v, 1}); } } } } cout << ⑤ << endl; return 0; } |
