题解
根据题意 当wls下降一定高度再回到原始高度之后体力值也会回复为原有值
可以将题意简化为如果想要登上高度大于h[1]+k高度的山时要将山缩减为h[1]+k的高度
按照这个规律建图 将无向边拆分为两条 通往高度大于h[1]+k的山的边代价增加与h[1]+k的高度差和0取max后平方
建图完毕后直接跑dijkstra加堆优化即可
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 10;
ll a[MAXN], cot[MAXN];
int n, m, k;
bool vis[MAXN];
struct node
{
ll v, w;
bool operator < (const node &oth) const
{
return w > oth.w;
}
};
vector<node> e[MAXN];
void dijkstra()
{
memset(cot, 0x3f, sizeof(cot));
cot[1] = 0;
priority_queue<node> pq;
pq.push({ 1, 0 });
while (!pq.empty())
{
ll u = pq.top().v, c = pq.top().w;
pq.pop();
vis[u] = 1;
for (node &i : e[u])
if (!vis[i.v] && c + i.w < cot[i.v])
cot[i.v] = c + i.w, pq.push({ i.v, cot[i.v] });
}
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
for (int i = 1; i <= m; i++)
{
ll u, v, w;
scanf("%lld%lld%lld", &u, &v, &w); //通往高度大于h[1]+k的山的边代价增加
e[u].push_back({ v, w + max(0LL, a[v] - a[1] - k) * max(0LL, a[v] - a[1] - k) });
e[v].push_back({ u, w + max(0LL, a[u] - a[1] - k) * max(0LL, a[u] - a[1] - k) });
}
dijkstra();
cout << cot[n] << endl;
return 0;
}