L2-001 紧急救援 (25 分)
Powered by:NEFU AB-IN
L2-001 紧急救援 (25 分)
-
题意
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
-
思路
题意:给定一张无向有权图,求出点1到点n的 最短路的数量 和 最短路中点权最大值
之前我们有做过无权图的最短路算法,那时候我们直接对 s p f a spfa spfa进行操作就好了
然而这道题, s p f a spfa spfa就不能直接操作,但是 d i j k s t r a dijkstra dijkstra就可以原因在于 d i j k s t r a dijkstra dijkstra中,每个点只被遍历一次,在它被操作前最后一次更新后dis和sum一定是固定的
但是spfa算法不一样,它并没有所谓“某次更新后就不会改变”的情况,spfa的最短路和最短路数在queue为空之前一直有被更新的可能,一个点可能进入queue多次所以dijkstra直接操作即可,而spfa不能直接操作(可以进行dp操作,记录每个点松弛前和松弛后的路径条数)
-
代码
/* * @Author: NEFU AB-IN * @Date: 2022-04-19 15:23:55 * @FilePath: \ACM\GPLT\L2-001.CPP * @LastEditTime: 2022-04-19 15:52:36 */ #include <bits/stdc++.h> using namespace std; #define int long long #define MP make_pair #define SZ(X) ((int)(X).size()) #define IOS \ ios::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0); #define DEBUG(X) cout << #X << ": " << X << endl; typedef pair<int, int> PII; const int INF = 0x3f3f3f3f; const int N = 1010; int st[N], dist[N], ww[N], num[N], people[N], pre[N]; vector<PII> g[N]; void dij(int s) { memset(pre, -1, sizeof pre); // 链表记录上一个节点是什么 memset(dist, 0x3f, sizeof dist); dist[s] = 0; ww[s] = people[s]; // 题目中的点权 num[s] = 1; //路径条数 priority_queue<PII, vector<PII>, greater<PII>> q; q.push({0, s}); while (q.size()) { auto t = q.top(); q.pop(); int u = t.second; if (st[u]) continue; st[u] = 1; for (auto [v, w] : g[u]) { if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; num[v] = num[u]; ww[v] = ww[u] + people[v]; pre[v] = u; q.push({dist[v], v}); } else if (dist[v] == dist[u] + w) //如果相等了,说明存在另一条最短路 { num[v] += num[u]; if (ww[v] < ww[u] + people[v]) // 需要更新点权的话就更新,顺便更新链表 { ww[v] = ww[u] + people[v]; pre[v] = u; } } } } } signed main() { IOS; int n, m, s, d; cin >> n >> m >> s >> d; for (int i = 0; i < n; ++i) cin >> people[i]; for (int i = 1; i <= m; ++i) { int u, v, w; cin >> u >> v >> w; g[u].push_back({v, w}); g[v].push_back({u, w}); } dij(s); cout << num[d] << " " << ww[d] << '\n'; vector<int> path; while (d != -1) { path.push_back(d); d = pre[d]; } reverse(path.begin(), path.end()); for (int i = 0; i < SZ(path); ++i) { cout << path[i] << " "[i == SZ(path) - 1]; } return 0; }
相关文章
- 程序人生:25岁我从零基础转到软件测试,我看到了前途...目前28K
- 《惢客创业日记》2021.01.25(周一)先干起来再说
- 《惢客创业日记》2019.08.25(周日)让谣言带上区块链的翅膀
- Flutter移动电商实战 --(25)列表页_使用Provide控制子类-1
- 3月25日,30秒知全网,精选7个热点///中兴通讯:多项6G潜在候选技术已完成///现代、起亚因起火风险在美召回超57万辆汽车
- 1052 Linked List Sorting (25 分)【难度: 一般 / 知识点: 链表】
- 资源 | 25个机器学习面试题,期待你来解答
- 【历史上的今天】8 月 25 日:Linux 诞生;我国第一个计算机科学技术研究所成立
- msp430入门学习25
- Linux下汇编语言学习笔记25 ---
- 25深入理解C指针之---传递数组