题目描述
爬山是wlswls最喜欢的活动之一。
在一个神奇的世界里,一共有nn座山,mm条路。
wlswls初始有kk点体力,在爬山的过程中,他所处的海拔每上升1m1m,体力会减11点,海拔每下降1m1m,体力会加一点。
现在wlswls想从11号山走到nn号山,在这个过程中,他的体力不能低于00,所以他可以事先花费一些费用请dlsdls把某些山降低,将一座山降低ll米需要花费l*ll∗l的代价,且每座山的高度只能降低一次。因为wlswls现在就在11号山上,所以这座山的高度不可降低。
wlswls从11号山到nn号山的总代价为降低山的高度的总代价加上他走过的路的总长度。
wlswls想知道最小的代价是多少。
输入描述
第一行三个整数nn,mm,kk。
接下来一行nn个整数,第ii个整数h_ihi表示第ii座山的高度。
接下来mm行,每行三个整数xx,yy,zz表示xyxy之间有一条长度为zz的双向道路。
经过每条路时海拔是一个逐步上升或下降的过程。
数据保证11号山和nn号山联通。
1 leq n, k, h_i, z leq 1000001≤n,k,hi,z≤100000
1 leq m leq 2000001≤m≤200000
1 leq x, y leq n1≤x,y≤n
x eq yx�=y
输出描述
一行一个整数表示答案。
样例输入 1
4 5 1 1 2 3 4 1 2 1 1 3 1 1 4 100 2 4 1 3 4 1
样例输出 1
6
题意:
定义两个山i,j之间的消耗dist(i,j) 我们通过题意应该知道,dist不仅仅与题中给距离有关,
还与山i和j的高度差 h 有关,如果h大于k,那么需要多消耗 (h-k)*(h-k) 。
我们依据上述的距离关系来跑最短路算法,即可得到我们想要的答案。
细节见代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d ",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), ' ', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;} inline void getInt(int* p); const int maxn = 1000010; const int inf = 0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ int n, m; ll k; struct node { int to; ll dist; int next; node() {} node(int tt, ll dd) { to = tt; dist = dd; } bool operator < (const node x)const { return dist > x.dist; } }; priority_queue<node> heap; int tot; node edge[maxn]; int head[maxn]; void addedge(int u, int v, int dist) { edge[tot].dist = dist; edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void init() { tot = 0; memset(head, -1, sizeof(head)); } ll h[maxn]; ll dis[maxn]; void dijkstra(int start) { // memset(dis,inf,sizeof(dis)); repd(i, 1, n) { dis[i] = 1e18; } dis[start] = 0; heap.push(node(start, 0ll)); node temp; while (!heap.empty()) { temp = heap.top(); heap.pop(); for (int i = head[temp.to]; i != -1; i = edge[i].next) { int v = edge[i].to; if (h[v] > k) { if (dis[v] > temp.dist + edge[i].dist + (h[v] - k) * (h[v] - k)) { dis[v] = temp.dist + edge[i].dist + (h[v] - k) * (h[v] - k); heap.push(node(edge[i].to, dis[v])); } } else { if (dis[v] > temp.dist + edge[i].dist) { dis[v] = temp.dist + edge[i].dist; heap.push(node(edge[i].to, dis[v])); } } } } } int main() { //freopen("D:\common_text\code_stream\in.txt","r",stdin); //freopen("D:\common_text\code_stream\out.txt","w",stdout); gbtb; cin >> n >> m >> k; repd(i, 1, n) { cin >> h[i]; } repd(i, 2, n) { h[i] -= h[1]; // 减去初始的高度方便后面处理 } init(); // 初始化链式前向星 int u, v, d; repd(i, 1, m) { cin >> u >> v >> d; addedge(u, v, d); // 加边 addedge(v, u, d); } dijkstra(1);// 跑最短路 cout << dis[n] << endl; // 输出答案 return 0; } inline void getInt(int* p) { char ch; do { ch = getchar(); } while (ch == ' ' || ch == ' '); if (ch == '-') { *p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 - ch + '0'; } } else { *p = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') { *p = *p * 10 + ch - '0'; } } }