当前位置: 首页 > news >正文

TRVCOST - Travelling cost 题解

题目复现

题目描述

Spojland 政府在城市中规划了一些地点,准备建设道路。

输入格式

第一行是一个整数 \(N\),表示政府计划修建的道路数量。

接下来有 \(N\) 行,每行包含三个整数 \(A\)\(B\)\(W\)。其中,\(A\)\(B\) 是修路连接的两个地点,\(W\) 是从 \(A\)\(B\) 或从 \(B\)\(A\) 的固定旅行费用。

再接下来的一行包含一个整数 \(U\),Rohit 希望从该地点出发,去往其他地方。

随后一行包含一个整数 \(Q\),代表他想要执行的查询次数,用于查找旅行费用。

接下来的 \(Q\) 行,每行包含一个整数 \(V\)(目的地),需要计算从 \(U\) 前往 \(V\) 的最低花费。

输出格式

对于每个查询,输出一行结果。如果无法从地点 \(U\) 到达地点 \(V\),则输出 'NO PATH'。

输入输出样例 #1

输入 #1

7
0 1 4
0 3 8
1 4 1
1 2 2
4 2 3
2 5 3
3 4 2
0
4
1
4
5
7

输出 #1

4
5
9
NO PATH

说明/提示

  • \(1 \le N \le 10^5\)
  • \(1 \le A, B \le 10^5\)
  • \(1 \le W \le 10^9\)
  • \(1 \le U \le 10^5\)
  • \(1 \le Q \le 10^5\)
  • \(1 \le V \le 10^5\)

题解

题目分析

很明显,这是一道单源最短路的题,可以使用 Dijkstra 来做这道题(如果是骗分的也可以试试 Floyd),而且还可以说这就是一道 Dijkstra 的版子。

接下来我将会简单说一下 Dijkstra。

Dijkstra

这个算法可以简单概括为“Dijkstra = BFS + 贪心”,大体步骤如下:

步骤 做法 具体操作 结果
\(1\) 从起点 \(s\) 出发,用 BFS 扩展它的邻居节点 把这些邻居点放到一个集合 \(A\) 中,并记录这些点到 \(s\) 的距离
\(2\) 选择距离 \(s\) 最近的邻居 \(v\),继续用 BFS 扩展 \(v\) 的邻居 首先在 \(A\) 中找到距离 \(s\) 最小的点 \(v\),把 \(v\) 的邻居点放到 \(A\) 中;如果 \(v\) 的邻居经过 \(v\) 中转,到 \(s\) 的距离更短,则更新这些邻居到 \(s\) 的距离;最后从集合 \(A\) 中移走 \(v\),后面不再处理 \(v\) 得到了从 \(s\)\(v\) 的最短路径;\(v\) 的邻居更新了到 \(s\) 的距离
\(3\) 重复步骤 \(2\),直到所有点都扩展到并计算完毕 集合 \(A\) 为空。计算出所有点到 \(s\) 的最短距离

按照这个步骤,实现 Dijkstra 其实并不难,现在给出参考实现代码。

实现

暴力做法(\(O(n^2)\)

struct edge {int v, w;
};vector<edge> e[MAXN];
int dis[MAXN], vis[MAXN];void dijkstra(int n, int s) {memset(dis, 0x3f, (n + 1) * sizeof(int));dis[s] = 0;for (int i = 1; i <= n; i++) {int u = 0, mind = 0x3f3f3f3f;for (int j = 1; j <= n; j++)if (!vis[j] && dis[j] < mind) u = j, mind = dis[j];vis[u] = true;for (auto ed : e[u]) {int v = ed.v, w = ed.w;if (dis[v] > dis[u] + w) dis[v] = dis[u] + w;}}
}

优先队列做法(\(O(m\log m)\)

struct edge {int v, w;
};struct node {int dis, u;bool operator>(const node& a) const { return dis > a.dis; }
};vector<edge> e[MAXN];
int dis[MAXN], vis[MAXN];
priority_queue<node, vector<node>, greater<node>> q;void dijkstra(int n, int s) {memset(dis, 0x3f, (n + 1) * sizeof(int));memset(vis, 0, (n + 1) * sizeof(int));dis[s] = 0;q.push({0, s});while (!q.empty()) {int u = q.top().u;q.pop();if (vis[u]) continue;vis[u] = 1;for (auto ed : e[u]) {int v = ed.v, w = ed.w;if (dis[v] > dis[u] + w) {dis[v] = dis[u] + w;q.push({dis[v], v});}}}
}

Dijkstra 总体上就这些内容了,那么接下来就可以编码了。

参考代码

#include<bits/stdc++.h>
#define int long long
#define Rint register int
#define fast_running ios::sync_with_stdio(false),std::cin.tie(nullptr),std::cout.tie(nullptr)
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 5, M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int m, s, cnt;
int head[N], dist[N], flag[N];
priority_queue<PII, vector<PII>, greater<PII>> q;     //优先队列优化 
struct edge {int from, to, next, w;
} e[M << 1];
void addedge(int u, int v, int w) {                   //建图 e[++cnt].from = u;e[cnt].to = v;e[cnt].next = head[u];e[cnt].w = w;head[u] = cnt;
}
void init() {                                         //初始化 for (int i = 0; i < N; i++) {head[i] = -1;flag[i] = 0;dist[i] = INF;}cnt = 0;return;
}
void dijshort(int start) {                            //优先队列优化的 Dijkstra dist[start] = 0;q.push({dist[start], start});while (!q.empty()) {PII tp = q.top();q.pop();int id_x = tp.second, dist_x = tp.first;if (flag[id_x]) continue;flag[id_x] = 1;for (int i = head[id_x]; i != -1; i = e[i].next) {int v = e[i].to;if (dist[v] > dist_x + e[i].w) {dist[v] = dist_x + e[i].w;q.push({dist[v], v});}}}
}
signed main() {fast_running;cin >> m;init();for (int i = 1; i <= m; i++) {int u, v, w;cin >> u >> v >> w;addedge(u, v, w);addedge(v, u, w);}cin >> s;dijshort(s);int T, in;cin >> T;while (T--) {cin >> in;if (dist[in] == INF) cout << "NO PATH\n";else cout << dist[in] << '\n';}return 0;
}
http://www.wuyegushi.com/news/114.html

相关文章:

  • 第一天
  • 111
  • 10
  • 7.26 4
  • DAY22
  • 30天总结-第二十六天
  • 周末
  • foobar2000 v2.24.6 汉化版
  • 今天做什么
  • 20天
  • OI集训 Day10
  • 【leetcode刷题】动态规划 Part4 经典线性DP
  • linux快照工具 timeshift
  • 关于LCD屏幕硬件参数
  • 今日总结
  • 莫队二次离线 学习笔记
  • 运算符
  • 进度
  • 软工7.26
  • DMY集训记录
  • Idea 构建 jar包
  • 2025 暑期模拟赛题目选记
  • 7月26日随笔
  • Learn Learn IdaPython
  • 启发式算法解析:经典思想、代表人物与前沿融合
  • day25
  • 线段树 tricks
  • 第一章
  • CVE-2022-41678 后台代码执行漏洞 (复现)