0
点赞
收藏
分享

微信扫一扫

最短路算法——Dijkstra(题目练习解析)

Dijkstra(题目练习解析)



点击 -> Dijkstra算法详细讲解


王国

题目描述

小明是王国的王子,今天是他登基之日。在即将成为国王之前,老国王给他出了道题,他想要考验小明是否有能力管理国家。

题目的内容如下:

蓝桥王国一共有 N 个建筑和 M 条单向道路,每条道路都连接着两个建筑,每个建筑都有自己编号,分别为 1∼N 。(其中皇宫的编号为 1)

国王想让小明回答从皇宫到每个建筑的最短路径是多少,但紧张的小明此时已经无法思考,请你编写程序帮助小明回答国王的考核。

输入描述

输入第一行包含三个正整数 N,M。

第 22 到 M + 1 行每行包含三个正整数 u,v,w,表示 uv 之间存在一条距离为 w 的路。

1 ≤ ≤ 3×10^5,1 ≤ ≤ 10^6,1 ≤ ui​,vi​ ≤ N,0 ≤ wi​ ≤ 10^9。

输出描述

输出仅一行,共 N 个数,分别表示从皇宫到编号为 1∼N 建筑的最短距离,两两之间用空格隔开。(如果无法到达则输出 -1)

样例输入

3 3 
1 2 1
1 3 5
2 3 2

样例输出

0 1 3

 参考代码:

#include<bits/stdc++.h>
using namespace std;

const long long INF = 0x3f3f3f3f3f3f3f3fLL; //这样定义INF的好处是: INF <= INF+x
const int NUM = 3e5+2;

struct edge{
    int from, to; long long w;
//边:起点,终点,权值。起点from并没有用到,e[i]的i就是from
    edge(int a, int b,long long c){from=a; to=b; w=c;}
};
vector<edge>e[NUM];           //用于存储图
struct s_node{
    int id; long long n_dis;   //id:结点;n_dis:这个结点到起点的距离
    s_node(int b,long long c){id=b; n_dis=c;}
    bool operator < (const s_node & a) const
    { return n_dis > a.n_dis;}
};
int n,m;
int pre[NUM]; //记录前驱结点
void print_path(int s, int t) {       //打印从s到t的最短路
    if(s==t){ printf("%d ", s); return; }  //打印起点
    print_path(s, pre[t]);              //先打印前一个点
    printf("%d ", t);                    //后打印当前点。最后打印的是终点t
}
long long  dis[NUM];         //记录所有结点到起点的距离
void dijkstra(){
    int s = 1;             //起点s是1
    bool done[NUM]; //done[i]=true表示到结点i的最短路径已经找到
    for (int i=1;i<=n;i++) {dis[i]=INF; done[i]=false; }    //初始化
    dis[s]=0;                           //起点到自己的距离是0
    priority_queue <s_node> Q;       //优先队列,存结点信息
    Q.push(s_node(s, dis[s]));       //起点进队列
    while (!Q.empty())   {
        s_node u = Q.top();           //pop出距起点s距离最小的结点u
        Q.pop();
        if(done[u.id])  //丢弃已经找到最短路径的结点。即集合A中的结点
            continue;
        done[u.id]= true;
        for (int i=0; i<e[u.id].size(); i++) {  //检查结点u的所有邻居
            edge y = e[u.id][i];         //u.id的第i个邻居是y.to
            if(done[y.to])               //丢弃已经找到最短路径的邻居结点
                continue;
            if (dis[y.to] > y.w + u.n_dis) {
                dis[y.to] = y.w + u.n_dis;
                Q.push(s_node(y.to, dis[y.to]));
                        //扩展新的邻居,放到优先队列中
                pre[y.to]=u.id;  //如果有需要,记录路径
            }
        }
    }
    // print_path(s,n);         //如果有需要,打印路径: 起点1,终点n
}


int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        e[i].clear();
    while (m--) {
        int u,v,w;
        scanf("%d%d%lld",&u,&v,&w);
        e[u].push_back(edge(u,v,w));
     // e[v].push_back(edge(v,u,w));    //本题是单向道路
    }
    dijkstra();
    for(int i=1;i<=n;i++){
        if(dis[i]>=INF) cout<<"-1 ";
        else printf("%lld ", dis[i]);
    }

    return 0;
}
举报

相关推荐

0 条评论