1018 Public Bike Management(多条最短路径,dijkstra+dfs+回溯)

 该题考查多条最短路径的计算,对比单条最短路,主要有两点不同:

1.在dijkstra算法中记录每个结点的所有相同最短距离的前结点

2.在dfs找多条最短路径时需要回溯状态

拿到所有最短路径以后,我们根据题意去获取相应的结果即可

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int c, n, s, m;
  4 typedef pair<int, int> pii;
  5 vector<int> number(505);
  6 vector<pii> graph[505];
  7 vector<bool> visited(505, false);
  8 vector<bool> dfs_vis(505, false);
  9 vector<int> dis(505, 0x3f3f3f3f);
 10 vector<int> record[505]; //record[i]表示最短路径上到i点之前的点
 11 set<pii> minHeap;
 12 vector<vector<int>> paths;
 13 
 14 void dijkstra() {
 15     dis[0] = 0;
 16     minHeap.insert(make_pair(0, 0));
 17     while(!minHeap.empty()) {
 18         auto node = minHeap.begin();
 19         int root = node -> second;
 20         visited[root] = true;
 21         minHeap.erase(node);
 22         for (auto i : graph[root]) {
 23             int child = i.first;
 24             int val = i.second;
 25             if (!visited[child]) {
 26                 if (dis[child] > dis[root] + val) {
 27                     minHeap.erase(make_pair(dis[child], child));
 28                     dis[child] = dis[root] + val;
 29                     minHeap.insert(make_pair(dis[child], child));
 30                     //只有一个距离最短的前结点
 31                     record[child].clear();
 32                     record[child].push_back(root);
 33                 } else if (dis[child] == dis[root] + val) {
 34                     //当存在多个距离相同的前结点时,一并记录到record数组中
 35                     record[child].push_back(root);
 36                 }
 37             }
 38         }
 39     }
 40 }
 41 //根据record进行遍历,注意record中记录的是前结点,所以这时要从问题站向PBMC遍历
 42 void dfs(int p, vector<int> path) { 
 43     path.push_back(p);
 44     dfs_vis[p] = true;
 45     if (p == 0) { //到达PBMC,保存当前路径
 46         paths.push_back(path);
 47         return;
 48     }
 49     for (auto i : record[p]) {
 50         if (!dfs_vis[i]) {
 51             vector<int> temp = path; //保留当前path信息
 52             dfs(i, temp);
 53             dfs_vis[i] = false; //回溯
 54         }
 55     }
 56     
 57 }
 58 int main() {
 59     cin >> c >> n >> s >> m;
 60     for (int i = 1; i <= n; ++ i) {
 61         cin >> number[i];
 62     }
 63     for (int i = 0; i < m; ++ i) {
 64         int si, sj, t;
 65         cin >> si >> sj >> t;
 66         graph[si].push_back(make_pair(sj, t));
 67         graph[sj].push_back(make_pair(si, t));
 68     }
 69     dijkstra();
 70     
 71     vector<int> temp;
 72     dfs(s, temp);
 73     
 74     int pc = c / 2; //完美情况
 75     int min_send = INT32_MAX, min_back = INT32_MAX;
 76     vector<int> res; //记录最终路径
 77     
 78     // 计算所有最短路径的send和back数量
 79     for (auto i : paths) {
 80         int send = 0; //需要从PBMC发出的单车数量
 81         int now = 0; //目前PBMCer手里有的单车数量
 82         for (auto j = ++(i.rbegin()); j != i.rend(); ++ j) {
 83             int station = *j;
 84             if (number[station] >= pc) { //站里有多的单车
 85                 now += number[station] - pc; //多的单车给PBMCer
 86             } else { //站里单车不够
 87                 if (now < pc - number[station]) { //加上PBMCer手里的也依旧不够
 88                     send += pc - number[station] - now;
 89                     now = 0;
 90                 } else { //PBMCer手里的够分
 91                     now -= pc - number[station];
 92                 }
 93             }
 94         }
 95         if (send < min_send) {
 96             min_send = send;
 97             res = i;
 98             min_back = now;
 99         } else if (send == min_send) {
100             if (now < min_back) {
101                 res = i;
102                 min_back = now;
103             }
104         }
105     }
106     
107     cout << min_send << " ";
108     for (auto i = res.rbegin(); i != res.rend();) {
109         cout << *i;
110         if (++ i != res.rend()) {
111             cout << "->";
112         }
113     }
114     cout << " " << min_back << endl; 
115 }

 

posted on 2024-11-15 21:24  Coder何  阅读(17)  评论(0)    收藏  举报