P4779 【模板】单源最短路径(标准版)

题目背景

2018年7月19日,某位同学在NOIDay1 T1归程-题里非常熟练地使用了-个广为人知的算法求最短
路。
然后呢?
100→60;
Ag→Cu;
最终,他因此没能与理想的大学达成契约。
小F衷心祝愿大家不再重蹈覆辙。
题目描述
给定一个n个点,m条有向边的带非负权图,请你计算从s出发,到每个点的距离。
数据保证你能从s出发到任意点。
输入格式
第一行为三个正整数n,m,s。第二行起m行,每行三个非负整数Ui,Vi, Wi,表示从ui到v;有一条权
值为Wi的有向边。
输出格式
输出一行n个空格分隔的非负整数,表示s到每个点的距离。

本题没有什么难的点,主要是考察对dijkstra的优化,本来想写个常用的priority_queue,但写出来后竟然给超内存,也不知道被我用到哪去了,纠结一番后,还是用现成的吧

#include
#include
#include
using namespace std;


const int MAX = 6000000;
const long long MAX2 = 2147483647;
int n,m,s;
long long aim[MAX];

struct df{
    long long w;
    int to;
    bool operator < (const struct df& a2)const{
         return  a2.w < w;
    }
};
struct node{
    int fr;
    int to;
    long long w;
}a[MAX];
int first[MAX];
int next[MAX];



priority_queue<struct df> pq;

void Djk(){
    
    while(!pq.empty()){
         struct df d;
         d =pq.top() ;
        pq.pop() ;
    
        if(aim[d.to] != d.w) continue; //为了删除原有结点 
        
        for(int i = first[d.to];i != 0;i = next[i]){
               
                if(aim[a[i].to] > a[i].w  + d.w){  //条件写对
                     aim[a[i].to] = a[i].w + d.w;
 
                
                     pq.push((df) { aim[a[i].to],a[i].to });  
                }
        }
    }
}

int main(){

    cin >> n >> m >> s;
    for(int i = 1;i <= m;i++){
          cin >> a[i].fr >> a[i].to >> a[i].w ;
          next[i] = first[a[i].fr];
          first[a[i].fr] = i;
    }
      struct df l;
      l.to = s;
      l.w = 0;
      pq.push(l); 
    

     for(int i = 1;i <= n;i++)
        aim[i] = MAX2;
        aim[s] = 0;

    Djk();
    for(int i = 1;i <= n;i++)
      cout << aim[i] << " ";
      return 0; 
}

最开始的时候我丝毫没意识到priority意味着什么,为了即时更新dis我一度想用指针做到在队列外更新 dis[i] = w + dis[j] 的同时做到队列中自动更新,最后看到别人的题解的时候我才意识到一个一直被我忽视了的问题,完全可以

加入一个新的 df结点 a1,新加入的结点的 w 一定比有着相同 to 的df结点 a2 的w小,即当a1,a2 同时在队列中时,一定是更新后的数据先进行松弛,不需要 a1 再进行一次松弛了,因此只要做到在 遇到 a1 时跳过就可以了,代码中

是根据    aim[d.to] != d.w    判定是 a2 还是 a1的,当然还可以通过 利用一个book数组进行标记

 

你可能感兴趣的:(P4779 【模板】单源最短路径(标准版))