CCPC-Wannafly Winter Camp Day1 (Div2, onsite)-F-爬爬爬山(dijkstra)

题目链接:https://www.zhixincode.com/contest/7/problem/F?problem_id=97

人话题意:n座山,每座山都有一个高度,海拔上升一米体力增加1点,下降一米减少1点。山与山之间有一个距离x,你可以降低山的高度l,代价为l*l,刚开始在1号山,要去n号山(最终体力值要大于等于零),求最小代价。

思路:刚开始在1号山,一定要下山,所以初始体力值应该为k + h[1],对于一座山,如果要砍,就一定要砍到(k + h[1])的高度为止,将这部分额外的花费加到边的权值上。注意双向边要分开来建。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e6+7;
#define inf 0x3f3f3f3f
#define pii pair<ll, ll>
int n, m, s, t, k;
ll d[maxn], h[maxn]; int vis[maxn];
vector<pair<int, ll>>E[maxn];
void init()
{
    for(int i = 0; i <= n; i++) E[i].clear();
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
}
void Dijkstra()
{
    d[s] = 0;
    priority_queue<pii> Q;
    //priority_queue<pii,vector<pii>,greater<pii> > Q;
    Q.push({-d[s],s});
    while(!Q.empty())
    {
        int now = Q.top().second;
        Q.pop(); if(vis[now]) continue;
        vis[now] = 1;
        for(int j = 0; j < E[now].size(); j++)
        {
            int v = E[now][j].first;
            if(!vis[v] && d[v] > d[now]+E[now][j].second)
            {
                d[v] = d[now]+E[now][j].second;
                Q.push({-d[v],v});
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        init(); scanf("%lld",&h[1]);
        k += h[1];
        for(int i = 2; i <= n; i++)
            scanf("%lld",&h[i]);

        int a, b; ll x;
        while(m--)
        {
            scanf("%d%d%lld",&a,&b,&x);
            if(h[b] >= k) E[a].push_back({b,x+(h[b]-k)*(h[b]-k)});
            else  E[a].push_back({b,x});
            if(h[a] >= k) E[b].push_back({a,x+(h[a]-k)*(h[a]-k)});
            else  E[b].push_back({a,x});
        }
        s = 1, t = n;
        Dijkstra();
        printf("%lld\n",d[t]);
    }
    return 0;
}

 

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/sugarbliss/article/details/86569486
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞