📅  最后修改于: 2023-12-03 14:58:22.423000             🧑  作者: Mango
本题是 Gate CS Mock 2018 的第 2 套试卷中的第 51 道题目。
给定一个有向无环图(DAG)和源顶点 S,求从 S 到其他所有顶点的最短路径的长度。请实现 Dijkstra 算法。
输入的第一行包含一个整数 T,表示测试数据组数。
对于每组测试数据,第一行包含三个整数 N、M 和 S。分别表示图中顶点的数量、边的数量和源顶点的编号。顶点编号从 1 开始。
接下来 M 行,每行包含三个整数 u、v 和 w,表示一条从顶点 u 到顶点 v 的有向边,边的长度为 w。
对于每组测试数据,输出 N-1 行,每行一个整数,第 i 行表示从 S 到顶点 i 的最短路径的长度。
如果从 S 到某个顶点不存在路径,则输出 -1。
2
3 3 1
1 2 2
2 3 1
1 3 4
3 2 1
1 2 2
2 3 1
2
3
-1
-1
首先,我们需要使用 C++ 中的 STL 中的优先队列 priority_queue 来实现 Dijkstra 算法。
我们定义一个 pair 结构体,用来保存当前顶点到源顶点 S 的距离,以及顶点的编号:
struct Pair {
int dist, node;
};
然后,我们定义一个 vector 数组 dist,初始化为 -1,用来保存顶点到源顶点 S 的最短距离:
vector<int> dist(n + 1, -1);
定义之后,我们将源顶点 S 到源顶点 S 的距离设为 0:
dist[S] = 0;
接下来,我们定义 STL 中的优先队列 priority_queue,用来保存所有可以到达的顶点及其到源顶点 S 的距离。在优先队列中,我们定义 greater
priority_queue<Pair, vector<Pair>, greater<Pair>> pq;
pq.push(make_pair(0, S));
然后,我们利用 STL 中的 vector 数组 graph,将所有的边存入其中。graph[i] 表示从顶点 i 出发可以到达的下一个顶点及其距离:
vector<pair<int, int>> graph[n + 1];
for (int i = 0; i < M; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back(make_pair(v, w));
}
最后,我们就可以进行核心算法:
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (auto v : graph[u]) {
int newDist = dist[u] + v.second;
if (dist[v.first] == -1 || dist[v.first] > newDist) {
dist[v.first] = newDist;
pq.push(make_pair(newDist, v.first));
}
}
}
完整代码如下:
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
using namespace std;
struct Pair {
int dist, node;
};
int main() {
int t;
cin >> t;
while (t--) {
int n, m, S;
cin >> n >> m >> S;
vector<int> dist(n + 1, -1);
dist[S] = 0;
priority_queue<Pair, vector<Pair>, greater<Pair>> pq;
pq.push(make_pair(0, S));
vector<pair<int, int>> graph[n + 1];
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back(make_pair(v, w));
}
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (auto v : graph[u]) {
int newDist = dist[u] + v.second;
if (dist[v.first] == -1 || dist[v.first] > newDist) {
dist[v.first] = newDist;
pq.push(make_pair(newDist, v.first));
}
}
}
for (int i = 1; i <= n; ++i) {
if (i != S) {
cout << dist[i] << endl;
}
}
}
return 0;
}
## 题目描述
本题是 Gate CS Mock 2018 的第 2 套试卷中的第 51 道题目。
给定一个有向无环图(DAG)和源顶点 S,求从 S 到其他所有顶点的最短路径的长度。请实现 Dijkstra 算法。
## 输入格式
输入的第一行包含一个整数 T,表示测试数据组数。
对于每组测试数据,第一行包含三个整数 N、M 和 S。分别表示图中顶点的数量、边的数量和源顶点的编号。顶点编号从 1 开始。
接下来 M 行,每行包含三个整数 u、v 和 w,表示一条从顶点 u 到顶点 v 的有向边,边的长度为 w。
## 输出格式
对于每组测试数据,输出 N-1 行,每行一个整数,第 i 行表示从 S 到顶点 i 的最短路径的长度。
如果从 S 到某个顶点不存在路径,则输出 -1。
## 样例输入
2 3 3 1 1 2 2 2 3 1 1 3 4 3 2 1 1 2 2 2 3 1
## 样例输出
2 3 -1 -1
## 程序实现
首先,我们需要使用 C++ 中的 STL 中的优先队列 priority_queue 来实现 Dijkstra 算法。
我们定义一个 pair 结构体,用来保存当前顶点到源顶点 S 的距离,以及顶点的编号:
struct Pair { int dist, node; };
然后,我们定义一个 vector 数组 dist,初始化为 -1,用来保存顶点到源顶点 S 的最短距离:
vector
定义之后,我们将源顶点 S 到源顶点 S 的距离设为 0:
dist[S] = 0;
接下来,我们定义 STL 中的优先队列 priority_queue,用来保存所有可以到达的顶点及其到源顶点 S 的距离。在优先队列中,我们定义 greater<Pair> 用来排序,将距离近的顶点先放入队列中:
priority_queue<Pair, vector
pq.push(make_pair(0, S));
然后,我们利用 STL 中的 vector 数组 graph,将所有的边存入其中。graph[i] 表示从顶点 i 出发可以到达的下一个顶点及其距离:
vector<pair<int, int>> graph[n + 1];
for (int i = 0; i < M; ++i) { int u, v, w; cin >> u >> v >> w; graph[u].push_back(make_pair(v, w)); }
最后,我们就可以进行核心算法:
while (!pq.empty()) { int u = pq.top().second; pq.pop();
for (auto v : graph[u]) { int newDist = dist[u] + v.second;
if (dist[v.first] == -1 || dist[v.first] > newDist) {
dist[v.first] = newDist;
pq.push(make_pair(newDist, v.first));
}
} }
完整代码如下:
#include
using namespace std;
struct Pair { int dist, node; };
int main() { int t; cin >> t;
while (t--) { int n, m, S; cin >> n >> m >> S;
vector<int> dist(n + 1, -1);
dist[S] = 0;
priority_queue<Pair, vector<Pair>, greater<Pair>> pq;
pq.push(make_pair(0, S));
vector<pair<int, int>> graph[n + 1];
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back(make_pair(v, w));
}
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
for (auto v : graph[u]) {
int newDist = dist[u] + v.second;
if (dist[v.first] == -1 || dist[v.first] > newDist) {
dist[v.first] = newDist;
pq.push(make_pair(newDist, v.first));
}
}
}
for (int i = 1; i <= n; ++i) {
if (i != S) {
cout << dist[i] << endl;
}
}
}
return 0; }