n头牛要从原来的位置到x位置再回到原先位置,求来回最短路中最长的花费。
从x回到原来位置可看作单源最短路,但每头牛到x位置的时间不能间接得出。因此将图取反,可转换为反向后的单源最短路来求。
这段代码的不足在于使用的spfa中有两段相似代码,可加以改进后使代码更加简洁。
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1000+20;
const int inf = 10e8+20;
struct edge {
int to, cost;
edge(int t, int c) : to(t), cost(c) {}
};
vector<edge> G1[maxn];
vector<edge> G2[maxn];
int d1[maxn];
int d2[maxn];
bool vis1[maxn];
bool vis2[maxn];
void spfa(int v, int s) {
queue<int> q1;
queue<int> q2;
fill(d1, d1 + v, inf);
fill(d2, d2 + v, inf);
memset(vis1, false, sizeof(vis1));
memset(vis2, false, sizeof(vis2));
d1[s] = d2[s] = 0;
q1.push(s);
q2.push(s);
vis1[s] = vis2[s] = true;
while (!q1.empty()) {
int p = q1.front();
q1.pop();
vis1[p] = false;
for (int i = 0; i < G1[p].size(); i++) {
edge u = G1[p][i];
if (d1[u.to] > d1[p] + u.cost) {
d1[u.to] = d1[p] + u.cost;
if (vis1[u.to] == false) {
q1.push(u.to);
vis1[u.to] = true;
}
}
}
}
while (!q2.empty()) {
int p = q2.front();
q2.pop();
vis2[p] = false;
for (int i = 0; i < G2[p].size(); i++) {
edge u = G2[p][i];
if (d2[u.to] > d2[p] + u.cost) {
d2[u.to] = d2[p] + u.cost;
if (vis2[u.to] == false) {
q2.push(u.to);
vis2[u.to] = true;
}
}
}
}
}
int main(int argc, char const *argv[]) {
int n, m, x;
scanf("%d%d%d", &n, &m, &x);
x--;
for (int i = 0; i < m; i++) {
int beg, end, cost;
scanf("%d%d%d", &beg, &end, &cost);
beg--, end--;
G1[beg].push_back(edge(end, cost));
G2[end].push_back(edge(beg, cost));
}
spfa(n, x);
int ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, d1[i] + d2[i]);
}
printf("%d\n", ans);
return 0;
}