CodeForces

Buy a Ticket 

题意:有n个点和m条路(都收费),n个点在开演唱会,门票不同,对于生活在n个点的小伙伴,要求计算出每个小伙伴为了看一场演唱会要花费的最小价格;

思路:

这道题我一开始觉得要对每一个点都跑一次最短路,

然而只用把dis【】的每个点初始化成每个地方的门票价格,在放入优先队列中,接着再跑一遍Dijkstra;

对Dijkstra刷新了认识。至于原理:

  (可以想明白,每次在队列中找到最小的门票价格去更新(松弛);

注意路费要计算来回;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 200000+7;

vector<pair<int,ll> >mp[maxn];
priority_queue<pair<ll,int> >q;
ll dis[maxn];


int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        ll c;
        scanf("%d%d%I64d",&u,&v,&c);    //因为long long 和int ;还有%I64d,wa了多次;
        mp[u].push_back(make_pair(v,c*2));
        mp[v].push_back(make_pair(u,c*2));
    }
   
    for(int i=1;i<=n;i++)
    {
        ll x;
        scanf("%I64d",&x);
        dis[i]=x;
        q.push(make_pair(-dis[i],i));
    }
    
    
    while(!q.empty())
    {
            int now = q.top().second;
            ll w = q.top().first;
            q.pop();
           
           if(dis[now] != -w)continue;          //这一步也比较重要;既然这个点被其他点松弛过,就不能去松弛别点;
            for(int t=0;t<mp[now].size();t++)  
            {
                int to = mp[now][t].first;
                if(dis[to]>dis[now]+mp[now][t].second)
                {
                    dis[to]=dis[now]+mp[now][t].second;
                    q.push(make_pair(-dis[to],to));
                }
            }
    }
    for(int i=1;i<=n;i++)
    {
       printf("%I64d%c",dis[i],i==n?'
':' ');
    }

    return 0;
}
原文地址:https://www.cnblogs.com/ckxkexing/p/8495197.html