CCPC-Wannafly Winter Camp Day1 爬爬爬山 (最短路)

题目描述

 

爬山是wlswls最喜欢的活动之一。

在一个神奇的世界里,一共有nn座山,mm条路。

wlswls初始有kk点体力,在爬山的过程中,他所处的海拔每上升1m1m,体力会减11点,海拔每下降1m1m,体力会加一点。

现在wlswls想从11号山走到nn号山,在这个过程中,他的体力不能低于00,所以他可以事先花费一些费用请dlsdls把某些山降低,将一座山降低ll米需要花费l*lll的代价,且每座山的高度只能降低一次。因为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 1000001n,k,hi,z100000

1 \leq m \leq 2000001m200000

1 \leq x, y \leq n1x,yn

x \neq 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\n",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), '\0', 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 == '\n');
    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';
        }
    }
}

 



posted @ 2019-05-20 21:45  茄子Min  阅读(222)  评论(0编辑  收藏  举报