zoukankan      html  css  js  c++  java
  • Codeforces-938D-Buy a Ticket(最短路设虚拟节点+Dijk优先队列优化)

    Describe

    Musicians of a popular band "Flayer" have announced that they are going to "make their exit" with a world tour. Of course, they will visit Berland as well.

    There are n cities in Berland. People can travel between cities using two-directional train routes; there are exactly m routes, i-th route can be used to go from city vi to city ui (and from ui to vi), and it costs wi coins to use this route.

    Each city will be visited by "Flayer", and the cost of the concert ticket in i-th city is ai coins.

    You have friends in every city of Berland, and they, knowing about your programming skills, asked you to calculate the minimum possible number of coins they have to pay to visit the concert. For every city i you have to compute the minimum number of coins a person from city i has to spend to travel to some city j (or possibly stay in city i), attend a concert there, and return to city i (if j ≠ i).

    Formally, for every  you have to calculate , where d(i, j) is the minimum number of coins you have to spend to travel from city i to city j. If there is no way to reach city j from city i, then we consider d(i, j) to be infinitely large.

    Input

    The first line contains two integers n and m (2 ≤ n ≤ 2·105, 1 ≤ m ≤ 2·105).

    Then m lines follow, i-th contains three integers viui and wi (1 ≤ vi, ui ≤ n, vi ≠ ui1 ≤ wi ≤ 1012) denoting i-th train route. There are no multiple train routes connecting the same pair of cities, that is, for each (v, u) neither extra (v, u) nor (u, v) present in input.

    The next line contains n integers a1, a2, ... ak (1 ≤ ai ≤ 1012) — price to attend the concert in i-th city.

    Output

    Print n integers. i-th of them must be equal to the minimum number of coins a person from city i has to spend to travel to some city j (or possibly stay in city i), attend a concert there, and return to city i (if j ≠ i).

    Examples
    input
    4 2
    1 2 4
    2 3 7
    6 20 1 25
    output
    6 14 1 25 
    input
    3 3
    1 2 1
    2 3 1
    1 3 1
    30 10 20
    output
    12 10 12 

    好题,可以学到很多。

    题意:乐队在每个城市开演唱会,各城市演唱会票价不同。求每个城市的人想要去一次演唱会的最小花费(来回车费+门票费)。

    思路:建一个虚拟节点(源点)0, 0到个节点的车费设为门票费。然后各个路费都二倍。题就变成了求,0点到各个城市的最短路问题(从各个城市到0的最短路)。

    坑点:

    1.这个题n范围很大,直接用邻接矩阵Dijk算法做会超时,要用邻接表存边,优先队列优化Dijk。

    2.花费范围也很大,所以权值变量要开long long int。

    3.要用标记数组在队列循环操作里剪枝,有点被走过了,就没必要再走了。否则会超时。


     1 //Dijk堆优化 
     2 //超级源点 
     3 //权值范围很大开long long 
     4 //要标记剪枝,否则会超时 
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<vector> 
     8 #include<queue>
     9 #define N 200005  //N很大所以要用邻接表 
    10 #define Inf 0x3f3f3f3f
    11 using namespace std;
    12 
    13 struct node{
    14     int v;
    15     long long w;
    16     bool operator < (const node & a) const{           
    17          return w > a.w;  
    18     }      
    19 };
    20 
    21 int n,m; 
    22 vector<node> G[N];
    23 long long dis[N];
    24 int mark[N];
    25 
    26 void Getmap(){
    27     int a,b;
    28     long long w;
    29     node p;
    30     for(int i=0;i<=n;i++)
    31         G[i].clear();
    32     for(int i=1;i<=m;i++){
    33         scanf("%d%d%lld",&a,&b,&w);
    34         p.v=b,p.w=w*2;
    35         G[a].push_back(p);
    36         p.v=a;
    37         G[b].push_back(p);
    38     }
    39     for(int i=1;i<=n;i++){    
    40         scanf("%lld",&w);
    41         p.v=i,p.w=w;
    42         G[0].push_back(p);    
    43     }
    44 }
    45 
    46 void Dijk(){
    47     node p;
    48     memset(dis,Inf,sizeof(dis));
    49     memset(mark,0,sizeof(mark));
    50     dis[0]=0;
    51     
    52     priority_queue<node> q;
    53     p.v=0,p.w=0;
    54     q.push(p);
    55     while(!q.empty()){
    56         p=q.top();
    57         q.pop();
    58         if(mark[p.v]) continue;//这个剪枝要有,要不会超时 
    59         mark[p.v]=1;
    60         for(int i=0;i<G[p.v].size();i++){
    61             node r=G[p.v][i];
    62             if(dis[r.v]>p.w+r.w){
    63                 dis[r.v]=p.w+r.w;
    64                 r.w=dis[r.v];
    65                 q.push(r);
    66             }
    67         }        
    68     }         
    69 }
    70 
    71 int main(){
    72     while(~scanf("%d%d",&n,&m)){
    73         Getmap();
    74         Dijk();
    75         for(int i=1;i<n;i++)
    76             printf("%lld ",dis[i]);
    77         printf("%lld
    ",dis[n]);        
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    gitee ssh key
    Visual Studio Code自定义快捷键(eclipse习惯)
    Maven settings.xml
    Android Studio
    windows压缩图片
    maven生成项目慢解决办法
    区块链学习专栏
    windows常用目录
    windows常用命令
    jQuery列表选择美化插件uichoose
  • 原文地址:https://www.cnblogs.com/yzhhh/p/9997599.html
Copyright © 2011-2022 走看看