自建电商网站有哪些宁波关键词优化品牌
目录
题目背景
题目描述
输入格式
输出格式
输入输出样例
说明/提示
代码
无注释版
有注释版
题目背景
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++; // 边计数器加 1e[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; // 起点的最短距离为 0q.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] << " ";}
}