P4779 【模板】单源最短路径(标准版)
题目背景
2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。
然后呢?
最终,他因此没能与理想的大学达成契约。
小 F 衷心祝愿大家不再重蹈覆辙。
题目描述
给定一个 n个点,m条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。
数据保证你能从 sss 出发到任意点。
输入格式
第一行为三个正整数 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
1 4 4
迪杰斯特拉的优化主要借助优先队列,优先关键字为到源点的距离
并且里面有用到一个知识点是结构体的优先队列怎么使用,这里用到了重载函数,这个重载函数在java中学到过,不过c++中也会有重载函数
下面了解一下什么是重载函数:
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator和其后要重载的运算符符号构成的
详情可见该博客:https://www.runoob.com/cplusplus/cpp-overloading.html
板子:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int u;//代表节点编号;
int l;//代表到起点的距离
node(int _u=0,int _l=0) : u(_u),l(_l) {};
};
bool operator <(node a,node b)
{
return a.l>b.l;
}
struct edge//储存边信息
{
int v;//代表终点
int w;//代表边权
edge(int _v=0,int _w=0) : v(_v),w(_w) {}
};
vector<edge>e[200001];//储存边信息
int book[100001];
int dis[100001];
int n;
void dijkstra(int s)
{
for(int i=1; i<=n; i++)
{
dis[i]=INF;
book[i]=0;
}
dis[s]=0;
priority_queue<node>que;
que.push(node(s,0));
while(!que.empty())
{
node top=que.top();
que.pop();
int u=top.u;//u代表top的编号
if(!book[u])
{
book[u]=1;
}
else
{
continue;
}
for(int i=0; i<e[u].size(); i++)
{
int v=e[u][i].v;
int w=e[u][i].w;
if(!book[v]&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
que.push(node(v,dis[v]));
}
}
}
}
int main()
{
int m,s;
cin>>n>>m>>s;
for(int i=1; i<=m; i++)
{
int u,v,w;
cin>>u>>v>>w;
e[u].push_back(edge(v,w));
}
dijkstra(s);
for(int i=1; i<=n; i++)
{
if(i==1)
{
cout<<dis[i];
}
else
{
cout<<" "<<dis[i];
}
}
cout<<endl;
return 0;
}