题意
有 n n n个点, m m m条边, t t t个加油站,每次加满油能走的最远距离为 d d d,结点 1 1 1和 n n n也算加油站,求 1 1 1到 n n n的最短距离
思路
先Floyd 跑一遍,找到每一对点之间的最短距离 。然后建立这样一个图:把所有的加油站和起点 1 1 1 和终点 n n n,放在一起 ,如果一对点的距离超过 d d d ,那么视为无法通过,最后在新图上跑一遍最短路。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 555;
const ll inf = 0x3f3f3f3f3f;
ll n, m, t, d;
ll a[N], dp[N][N];
int main()
{
ios::sync_with_stdio(false);
cout.tie(NULL);
memset(dp, inf, sizeof(dp));
cin >> n >> m >> t >> d;
for(ll i = 1; i <= t; i++)
cin >> a[i];
a[t+1] = 1, a[t+2] = n;
for(ll i = 1; i <= m; i++)
{
ll u, v, w;
cin >> u >> v >> w;
dp[u][v] = w;
dp[v][u] = w;
}
for(ll k = 1; k <= n; k++)
for(ll i = 1; i <= n; i++)
for(ll j = 1; j <= n; j++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
for(ll i = 1; i <= t+2; i++)
for(ll j = 1; j <= t+2; j++)
if(dp[a[i]][a[j]] > d)
dp[a[i]][a[j]] = inf;
for(ll k = 1; k <= t+2; k++)
for(ll i = 1; i <= t+2; i++)
for(ll j = 1; j <= t+2; j++)
{
ll u = a[k], v = a[i], w = a[j];
dp[v][w] = min(dp[v][w], dp[v][u] + dp[u][w]);
}
if(dp[1][n] == inf)
cout << "stuck" << endl;
else
cout << dp[1][n] << endl;
return 0;
}