首页 > 其他分享 >洛谷 模板 单源最短路径(标准版)

洛谷 模板 单源最短路径(标准版)

时间:2024-07-25 22:57:14浏览次数:18  
标签:cnt 洛谷 min int 单源 距离 标准版 节点 dis

原题p4779

题目背景

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。

然后呢?

100→60;

Ag→Cu;

最终,他因此没能与理想的大学达成契约。

小 F 衷心祝愿大家不再重蹈覆辙。

题目描述

给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。

数据保证你能从 s 出发到任意点。

输入格式

第一行为三个正整数 n,m,s。 第二行起 m 行,每行三个非负整数 ui​,vi​,wi​,表示从ui​ 到 vi​ 有一条权值为 wi​ 的有向边。

输出格式

输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。

输入输出样例

输入 #1

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出 #1

0 2 4 3

说明/提示

fill函数用法

赋初值:fill(l ,r , num) 意为给[l,r-1]区间赋值num

超时代码

时间复杂度 O(n^2)

#include <iostream>  // 引入输入输出流库   
#include <algorithm> // 引入算法库(本例中主要为了使用fill函数)  
using namespace std; 
  
const int N = 1E5 + 5; // 定义节点数上限  
const int M = 2E5 + 5; // 定义边数上限  
int n, m, s;           // 分别表示节点数、边数和起点  
  
struct edge {          // 定义边结构体  
    int d;             // 边的权重  
    int to;            // 边的终点  
    int next;          // 链表的下一个节点索引  
} e[M];                // 定义边数组  
  
int dis[N], h[N], cnt; // 分别表示距离数组、邻接表头节点数组和边计数器  
bool vis[N];           // 标记节点是否已被访问  
  
// 查找当前未访问节点中距离最小的节点索引  
int min_dis() {    
    int min = 0x7fffffff, min_idx = 0;    
    for (int i = 1; i <= n; i++) {    
        if (!vis[i] && min > dis[i]) {    
            min = dis[i];    
            min_idx = i;    
        }    
    }    
    return min_idx;    
}    
  
// 向邻接表中添加边  
void add(int u, int v, int d) {    
    cnt++;    
    e[cnt].to = v;    
    e[cnt].d = d;    
    e[cnt].next = h[u];    
    h[u] = cnt;    
}    
  
// 执行Dijkstra算法计算最短路径  
void Dijkstra() {    
    fill(dis + 1, dis + n + 1, 0X7fffffff); // 初始化距离数组为正无穷大  
    dis[s] = 0;  // 起点到自身的距离为0  
        
    for (int i = 1; i <= n; i++) {    
        int k = min_dis();  // 找到当前未访问节点中距离最小的节点  
        vis[k] = true;  // 标记该节点为已访问  
        for (int j = h[k]; j; j = e[j].next) {  // 遍历该节点的所有邻接边  
            int y = e[j].to;  // 邻接边的终点  
            if (!vis[y] && dis[y] > dis[k] + e[j].d) {  // 如果该节点未访问且通过当前节点到达它的距离更短  
                dis[y] = dis[k] + e[j].d;  // 更新距离  
            }    
        }    
    }    
}    
  
int main() {    
    cin >> n >> m >> s;  // 输入节点数、边数和起点  
    for (int i = 1; i <= m; i++) {    
        int u, v, d;    
        cin >> u >> v >> d;  // 输入每条边的起点、终点和权重  
        add(u, v, d);  // 向邻接表中添加边  
    }    
    Dijkstra();  
    for (int i = 1; i <= n; i++) {    
        if (dis[i] != 0X7fffffff) cout << dis[i] << " ";  // 输出每个节点的最短距离(排除正无穷大)  
    }    
    cout << endl;    
    return 0;    
}

AC代码

时间复杂度O((n+m)log​n)

#include <iostream>  
#include <queue>  
#include <algorithm>  
using namespace std;  
  
const int N = 1E5 + 5;   
const int M = 2E5 + 5; 
int n,m,s; 
struct edga { 
    int d;       
    int to;    
    int next;  
} e[M];  
  
int dis[N], h[N], cnt; 
bool vis[N];           
  
// 自定义节点结构体,用于优先队列  
struct node {  
    int pos;  // 节点位置  
    int dis;  // 从起点到该节点的距离  
    // 重载小于运算符,使得优先队列按照距离从小到大排序  
    bool operator <(const node &x) const {  
        return x.dis < dis;  
    }  
};  
  
priority_queue<node> q; // 优先队列,用于存储待处理的节点及其距离  
  
// 向邻接表中添加边  
void add(int u, int v, int d) {  
    cnt++;  
    e[cnt].to = v;  
    e[cnt].next = h[u];  
    e[cnt].d = d;  
    h[u] = cnt;  
}  
   
void Dijkstra() {  
    dis[s] = 0;  
    q.push({s, 0});   
    while (!q.empty()) {  
        node temp = q.top(); 
        q.pop();  
        int x = temp.pos, d = temp.dis;  
        if (vis[x]) continue; 
        vis[x] = 1; 
        for (int i = h[x]; i; i = e[i].next) {  
            int y = e[i].to;  
            dis[y] = min(dis[y], e[i].d + d);   
            if (!vis[y]) q.push({y, dis[y]});
        }  
    }  
}  
  
int main() {  
    cin >> n >> m >> s; 
 	fill(dis + 1, dis + n + 1, 0X7fffffff);  
    for (int i = 1; i <= m; i++) {  
        int u, v, d;  
        cin >> u >> v >> d;  
        add(u, v, d);  
    }  
    Dijkstra();   
    for (int i = 1; i <= n; i++) {  
        if (dis[i] != 0x7fffffff) printf("%d ", dis[i]);  
    }  
    return 0;
}

标签:cnt,洛谷,min,int,单源,距离,标准版,节点,dis
From: https://blog.csdn.net/j2189259313/article/details/140665549

相关文章

  • 洛谷 跳石头
    原题题目描述一年一度的“跳石头”比赛又要开始了!这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直......
  • 洛谷题单指南-前缀和差分与离散化-P1314 [NOIP2011 提高组] 聪明的质监员
    原题链接:https://www.luogu.com.cn/problem/P1314题意解读:计算m个检验值之和,计算与s差值绝对值的最小值。解题思路:1、首先要搞懂检验值是如何计算的如上图,对于每一个区间的检验值yi,表示为:yi="该区间重量>=W的矿石个数" ✖️"该区间>=W的矿石价值之和"检验值y即所有yi(1<=......
  • 洛谷 P1161 开灯
    目录题目-开灯题目描述输入格式输出格式样例#1样例输入#1样例输出#1提示ACCODE思路ACCODEC++说明使用Map做数据标记,会出现TEL向下取整<math.h>中常用的函数题目-开灯题目描述在一条无限长的路上,有一排无限长的路灯,编号为1,2,3,4,······。每一盏灯......
  • 洛谷刷题题单
    【算法1-1】模拟与高精度 [NOIP2003普及组]乒乓球 [NOIP2003普及组]乒乓球......
  • 洛谷题单指南-前缀和差分与离散化-P8218 【深进1.例1】求区间和
    原题链接:https://www.luogu.com.cn/problem/P8218题意解读:对于数组a[N],给定m个区间l~r,求每个区间所有元素之和。解题思路:先思考暴力做法:对于每一个区间[l,r],累加a[l]~a[r]所有元素,时间复杂度最坏为10^5*10^4,不可行。一维前缀和:设s[N]是a[N]的前缀和数组,即对于每一个s[i......
  • 线段树(区间操作,例题:洛谷P3372 线段树 1)
    在上一节线段树(原理、构造和区间查询,例题:BalancedLineup)中介绍了线段树的构造,下面就来说一下它的区间操作。区间操作与Lazy-Tag有关,如果修改操作是对区间内的每个元素一一修改,就会比较繁琐低效,目前的解决办法是线段树的tree[i].data记录的是区间i的值(详细见上节),可以再定义一......
  • 洛谷P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
    [NOIP2001普及组]最大公约数和最小公倍数问题题目描述洛谷题目链接:https://www.luogu.com.cn/problem/P1029输入两个正整数x,y,求出满足下列条件的P,Q的个数:P,Q是正整数。要求P,Q以x为最大公约数,以y为最小公倍数。试求:满足条件的所有可能的P,Q的个数。......
  • [NOIP2008 提高组] 笨小猴(洛谷题号P1125)
    [NOIP2008提高组]笨小猴题目描述笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的......
  • 洛谷P10693
    洛谷P10693好奇怪的题目编号题面\(n\)个人,\(2n\)个座位,每个人都有心仪的座位,如\(i\)心仪的座位为\(a_i\)(可重复),设计师设计让他们坐在自己编号的位置上,即\(i\)做到\(i\),每个人只可以做\(a_i\)或\(i\),最多多少个人坐到心仪的座位。思路提取input11213453799111112......
  • 洛谷算法题
    目录数字反转迪杰斯特拉算法背包问题字符串排序P1192台阶问题P1111修复公路炸铁路问题计数问题......