1 of 2

五、完善程序-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;
}
Scroll to Top