选择最佳路线
题目
思路
比较简单的题,可以建立虚拟源点或者建立反向边,都是比较简单的思路,这里直接上各种思路的代码
Code
Dijkstra建立反向边
#include <iostream>
#include <cstring>
#include <queue>
using i64 = long long;
const int N = 1e3 + 10, M = 2e4 + 1010;
int n, m, s;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c) {
ne[idx] = h[a], h[a] = idx, e[idx] = b, w[idx ++] = c;
}
void dijkstra(int s) {
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
std::priority_queue<std::pair<int, int>> h1;
dist[s] = 0;
h1.push({0, s});
while (h1.size()) {
auto t = h1.top(); h1.pop();
int u = t.second;
if (st[u]) continue;
st[u] = true;
// std::cout << u << "\n";
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[u] + w[i]) {
dist[j] = dist[u] + w[i];
h1.push({-dist[j], j});
}
}
}
}
int main() {
while (std::cin >> n >> m >> s) {
memset(h, -1, sizeof h);
idx = 0;
for (int i = 1; i <= m; i ++) {
int p, q, t;
std::cin >> p >> q >> t;
add(q, p, t);
}
dijkstra(s);
int t;
std::cin >> t;
int res = 0x3f3f3f3f;
for (int i = 1; i <= t; i ++) {
int k;
std::cin >> k;
res = std::min(res, dist[k]);
}
if (res == 0x3f3f3f3f) res = -1;
std::cout << res << "\n";
}
}
SPFA建立反向边
#include <iostream>
#include <cstring>
#include <queue>
using i64 = long long;
const int N = 1e3 + 10, M = 2e4 + 1010;
int n, m, s;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c) {
ne[idx] = h[a], h[a] = idx, e[idx] = b, w[idx ++] = c;
}
void spfa(int s) {
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
std::queue<int> q1;
q1.push(s);
dist[s] = 0;
while (q1.size()) {
int t = q1.front(); q1.pop();
st[t] = false;
for (int i = h[t]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if (!st[j]) {
q1.push(j);
st[j] = true;
}
}
}
}
}
int main() {
while (std::cin >> n >> m >> s) {
memset(h, -1, sizeof h);
idx = 0;
for (int i = 1; i <= m; i ++) {
int p, q, t;
std::cin >> p >> q >> t;
add(q, p, t);
}
spfa(s);
int t;
std::cin >> t;
int res = 0x3f3f3f3f;
for (int i = 1; i <= t; i ++) {
int k;
std::cin >> k;
res = std::min(res, dist[k]);
}
if (res == 0x3f3f3f3f) res = -1;
std::cout << res << "\n";
}
}
Dijkstra建立虚拟源点
#include <iostream>
#include <cstring>
#include <queue>
using i64 = long long;
const int N = 1e3 + 10, M = 2e4 + 1010;
int n, m, s;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c) {
ne[idx] = h[a], h[a] = idx, e[idx] = b, w[idx ++] = c;
}
void dijkstra(int s) {
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
std::priority_queue<std::pair<int, int>> h1;
dist[s] = 0;
h1.push({0, s});
while (h1.size()) {
auto t = h1.top(); h1.pop();
int u = t.second;
if (st[u]) continue;
st[u] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
h1.push({-dist[v], v});
}
}
}
}
int main() {
while (std::cin >> n >> m >> s) {
memset(h, -1, sizeof h);
idx = 0;
for (int i = 1; i <= m; i ++) {
int p, q, t;
std::cin >> p >> q >> t;
add(p, q, t);
}
int w;
std::cin >> w;
for (int i = 1; i <= w; i ++) {
int k;
std::cin >> k;
add(0, k, 0);
}
dijkstra(0);
if (dist[s] == 0x3f3f3f3f) std::cout << -1 << "\n";
else std::cout << dist[s] << "\n";
}
}
SPFA建立虚拟源点
#include <iostream>
#include <cstring>
#include <queue>
using i64 = long long;
const int N = 1e3 + 10, M = 2e4 + 1010;
int n, m, s;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];
void add(int a, int b, int c) {
ne[idx] = h[a], h[a] = idx, e[idx] = b, w[idx ++] = c;
}
void spfa(int s) {
memset(dist, 0x3f, sizeof dist);
memset(st, false, sizeof st);
std::queue<int> q1;
q1.push(s);
dist[s] = 0;
while (q1.size()) {
int t = q1.front(); q1.pop();
st[t] = false;
for (int i = h[t]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if (!st[j]) {
q1.push(j);
st[j] = true;
}
}
}
}
}
int main() {
while (std::cin >> n >> m >> s) {
memset(h, -1, sizeof h);
idx = 0;
for (int i = 1; i <= m; i ++) {
int p, q, t;
std::cin >> p >> q >> t;
add(p, q, t);
}
int w;
std::cin >> w;
for (int i = 1; i <= w; i ++) {
int k;
std::cin >> k;
add(0, k, 0);
}
spfa(0);
if (dist[s] == 0x3f3f3f3f) std::cout << -1 << "\n";
else std::cout << dist[s] << "\n";
}
}