> Dijkstra算法用于解决单源最短路径问题,本质其实是一种贪心
单元最短路径
请编写程序求给定正权有向图的单源最短路径长度。图中包含n个顶点,编号为0至n-1,以顶点0作为源点。
输入格式:
输入第一行为两个正整数n和e,分别表示图的顶点数和边数,其中n不超过20000,e不超过1000。接下来e行表示每条边的信息,每行为3个非负整数a、b、c,其中a和b表示该边的端点编号,c表示权值。各边并非按端点编号顺序排列。
输出格式:
输出为一行整数,为按顶点编号顺序排列的源点0到各顶点的最短路径长度(不含源点到源点),每个整数后一个空格。如源点到某顶点无最短路径,则不输出该条路径长度
作者 朱允刚
单位 吉林大学
> 利用c++里的数据结构,建立邻接表(有向图)
用多个数据储存表,记录最小权重
看代码讲解前需
- 了解pair类型及其用法
- 熟悉队列和优先队列的访问,存储
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;//定义无穷大
int n, e;//节点个数,边数
typedef pair<int, int> pii;//定义pair<int ,int>类型为pii;
//(目标点,距离)
const int N = 20010;
int dist[N];//用来记录源点到其他各个点最小权重数
vector<pii> g[N];//由许多pair数组组成的容器
int main()
{
cin >> n >> e;
// 先都初始化为无穷大
memset(dist, INF, sizeof dist);
while (e--)
{
int a, b, c;
cin >> a >> b >> c;//点,点,边的权重
g[a].push_back({ b,c });
//存储a顶点发出的指向b顶点的边,此边权重为c;
}
dist[0] = 0;//源点到自己的距离为0
priority_queue<pii, vector<pii>, greater<pii>> pq;//优先队列里面的小顶堆,由小到大
//快速排序,将权重小的放在前面
pq.push({ 0,0 });
//先把源点到自己的距离放进去,位于队首
while (!pq.empty())
{
int w = pq.top().first;//取pair类型队首元素(用两个变量)
//队首的权重数最小
int md = pq.top().second;
//因为优先队列会自动排序,所以在前面的默认是权重最小的
pq.pop();//队首出队操作
if (dist[md] > w) continue;//如果当前距离不是最短距离,跳过
//注意此处一定是>0,要让md==0时可以正常进行下面的操作
//g[md]里面存的是多个pii类型的数据(目标点,权重)
for (auto t : g[md])//自动识别类型t
//遍历当前节点所有的邻接点
{
int tt = t.first;
int ww = t.second;
//由上一点指向下一点,如果到这点的路径大于目前指向的
//值得注意的是,前面有一步操作是将dist里面位置的路径先假设为无穷大
if (dist[tt] > dist[md] + ww)//找最短路径
{
dist[tt] = dist[md] + ww;
pq.push({ dist[tt],tt });
//优先队列里面前面是权重,后面是目标点,便于STL排序
//
//将目前由源点指向的点及其权重压入优先队列
}
}
}
for (int i = 1; i < n; i++)
{
if (dist[i] != INF)
cout << dist[i] << ' ';
}
return 0;
}