当前位置: 首页 > news >正文

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 到每个点的距离。

输入输出样例

输入 

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

输出 

0 2 4 3

说明/提示

样例解释请参考 数据随机的模板题。

1≤n≤105;

1≤m≤2×105;

s=1;

1≤ui​,vi​≤n;

0≤wi​≤109,

0≤∑wi​≤109。

代码

无注释版

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
struct edge{
	int to,dis,next;
}e[N];
int head[N],dis[N],cnt;
bool vis[N];
int m,n,s;
void addedge(int u,int v,int d){
	cnt++;
	e[cnt].dis=d;
	e[cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
struct node{
	int dis;
	int pos;
	bool operator <(const node &x)const{
		return x.dis<dis;
	}
};
priority_queue<node> q;
void dijkstra(){
	dis[s]=0;
	q.push({0,s});
	while(!q.empty()){
		node t=q.top();
		q.pop();
		int x=t.pos,d=t.dis;
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=head[x];i;i=e[i].next){
			int y=e[i].to;
			if(dis[y]>dis[x]+e[i].dis){
				dis[y]=dis[x]+e[i].dis;
				if(!vis[y]){
					q.push({dis[y],y});
				}
			}
		}
	}
}
signed main(){
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++){
		dis[i]=INT_MAX;
	}
	for(int i=0;i<m;i++){
		int a,b,c;
		cin>>a>>b>>c;
		addedge(a,b,c);
	}
	dijkstra();
	for(int i=1;i<=n;i++){
		cout<<dis[i]<<" ";
	}
} 

有注释版

#include<bits/stdc++.h>  // 引入 C++ 标准库,包含常用的输入输出、容器、算法等
using namespace std;  // 使用标准命名空间,避免每次都加 std::

#define int long long  // 将 int 类型替换为 long long,确保能够处理更大的数值范围
const int N = 1e6 + 10;  // 定义最大节点数的常量,N 用来存储最大节点数和边数
struct edge {  // 定义一个结构体表示边
    int to, dis, next;  // `to` 表示边的目标节点,`dis` 表示边的权值,`next` 用来链接下一条边
} e[N];  // 用数组 `e` 存储所有边
int head[N], dis[N], cnt;  // `head` 数组用于存储每个节点的边的起始位置,`dis` 数组存储最短距离,`cnt` 是边的计数器
bool vis[N];  // `vis` 数组表示节点是否被访问过
int m, n, s;  // `n` 是节点数,`m` 是边数,`s` 是起始节点

// 添加一条边的方法
void addedge(int u, int v, int d) {
    cnt++;  // 边计数器加 1
    e[cnt].dis = d;  // 设置边的权值
    e[cnt].to = v;  // 设置边的目标节点
    e[cnt].next = head[u];  // 将当前边插入到 `u` 的边链表头部
    head[u] = cnt;  // 更新 `u` 节点的边链表头
}

// 定义节点结构体,用于优先队列中存储节点和其对应的最短距离
struct node {
    int dis;  // 节点的当前最短距离
    int pos;  // 节点的位置(编号)
    bool operator <(const node &x) const {  // 重载小于运算符,用于优先队列中的排序(按最短距离排序)
        return x.dis < dis;  // 小的优先
    }
};

priority_queue<node> q;  // 优先队列,用来存储节点及其最短距离

// Dijkstra 算法实现
void dijkstra() {
    dis[s] = 0;  // 起点的最短距离为 0
    q.push({0, s});  // 将起点加入优先队列
    while (!q.empty()) {  // 当队列不为空时,继续计算
        node t = q.top();  // 取出最小距离的节点
        q.pop();  // 从队列中移除该节点
        int x = t.pos, d = t.dis;  // `x` 是节点编号,`d` 是该节点的当前最短距离
        if (vis[x]) continue;  // 如果该节点已经访问过,跳过
        vis[x] = 1;  // 标记节点 `x` 已经访问
        // 遍历当前节点 `x` 的所有邻接节点
        for (int i = head[x]; i; i = e[i].next) {
            int y = e[i].to;  // 获取目标节点 `y`
            if (dis[y] > dis[x] + e[i].dis) {  // 如果通过当前节点 `x` 到节点 `y` 的距离更短
                dis[y] = dis[x] + e[i].dis;  // 更新 `y` 的最短距离
                if (!vis[y]) {  // 如果 `y` 还没有被访问过
                    q.push({dis[y], y});  // 将 `y` 加入队列,更新它的最短距离
                }
            }
        }
    }
}

signed main() {
    cin >> n >> m >> s;  // 输入节点数 `n`,边数 `m`,起始节点 `s`
    for (int i = 1; i <= n; i++) {  // 初始化所有节点的最短距离为无穷大
        dis[i] = LLONG_MAX;
    }
    for (int i = 0; i < m; i++) {  // 输入每一条边,并构建图
        int a, b, c;
        cin >> a >> b >> c;  // 输入边的起始节点 `a`,目标节点 `b`,权值 `c`
        addedge(a, b, c);  // 添加边
    }
    dijkstra();  // 执行 Dijkstra 算法,计算最短距离
    for (int i = 1; i <= n; i++) {  // 输出从起点 `s` 到所有节点的最短距离
        cout << dis[i] << " ";
    }
}

文章转载自:

http://lTcujvIK.wnqfz.cn
http://JbeT8dBL.wnqfz.cn
http://0Cn0jrhI.wnqfz.cn
http://YUBmpwmH.wnqfz.cn
http://KHnB1Wpc.wnqfz.cn
http://wxccf0wE.wnqfz.cn
http://PdZbVg8C.wnqfz.cn
http://oucUy4eT.wnqfz.cn
http://VnEgBKpP.wnqfz.cn
http://YtoM0qYV.wnqfz.cn
http://DH7TNkyd.wnqfz.cn
http://ce7DsSuo.wnqfz.cn
http://Kh2Afx4y.wnqfz.cn
http://4PTZpLiu.wnqfz.cn
http://2SNioKVp.wnqfz.cn
http://eEByj4h9.wnqfz.cn
http://v5v3wqxt.wnqfz.cn
http://0z891km7.wnqfz.cn
http://YGvPUjdy.wnqfz.cn
http://hXW3cvKL.wnqfz.cn
http://spH6PU6Q.wnqfz.cn
http://Rm8JxCrn.wnqfz.cn
http://ELMZ3ArN.wnqfz.cn
http://7ZQeRD6q.wnqfz.cn
http://bsfdfczR.wnqfz.cn
http://DUiBnOsA.wnqfz.cn
http://OG1UFCGf.wnqfz.cn
http://3olE1yxM.wnqfz.cn
http://6qdYgQPA.wnqfz.cn
http://U0fWauJa.wnqfz.cn
http://www.dtcms.com/a/116383.html

相关文章:

  • Vue CLI创建项目指南
  • 【leetcode100】买卖股票的最佳时机
  • 小家电等电子设备快充方案,XSP15支持全协议和支持MCU与电脑传输数据
  • 自动化备份全网服务器数据平台
  • 快手Python开发面经及参考答案
  • Android Canvas动画实践:实现小球旋转、扩散、聚合效果
  • VS2022远程调试Linux程序
  • LeetCode 1863. 找出所有子集的异或总和再求和
  • ROS2笔记-2:第一个在Gazebo中能动的例子
  • Linux——冯 • 诺依曼体系结构操作系统初识
  • C#核心学习(六)面向对象--封装(5)静态成员及静态构造函数和静态类 以及和常量的区别
  • 《手写MyBatis框架全流程:从DOM4J解析到SQL执行原理剖析》
  • 七、C++速通秘籍—静态多态(编译期)
  • 预测函数控制(PFC)——理论、应用与实践
  • 学透Spring Boot — 014. Spring MVC的自动配置
  • CANoe CAPL——CAN CAPL函数
  • jQuery 文本属性值
  • OceanBase生态2.0:如何实现“三分天下有其一”?
  • 应用层自定义协议与序列化
  • 【AI提示词】大学教授学术阅读(读论文)
  • 基于SpringBoot的售楼管理系统【附源码】
  • 记一次常规的网络安全渗透测试
  • SpringMVC与SpringCloud的区别
  • 区块链赋能知识产权保护:用技术捍卫创作者的权利
  • 下载安装Node.js及其他环境
  • 什么是异步?
  • ChatGPT-4o 在汉字显示上进步巨大
  • 解锁多邻国:全方位语言学习新体验
  • Gateway 网关 快速开始
  • NAT技术、代理服务器和内网穿透