【笔记/模板】Dijkstra算法

原理解释

Dijkstra算法是通过贪心+BFS+动态规划实现的,可以用来计算单个点(源点)到其余任一点的距离大小。

Dijkstra算法的实现分为以下几步:

  • 定义并初始化数组dis[N],其中 \(dis_{i}\) 表示源点当前距离 \(i\) 点的最短距离,再定义一个 \(bool\) 数组 vis[N]\(vis_{i}\) 代表第 \(i\) 个点是否被拓展过(即是否达到了最优解)。

  • 从未被拓展的点中找出一个离源点最近的点 \(x\)(此时它已经是最优解),通过这个点依次松弛和它联通的每一个点距离源点的距离,同时将所松弛的点加入到队列当中。

  • 等到队列中没有元素存在之后,结束函数,此时 dis[N] 中的每个点 \(dis_{i}\) 即代表着距离源点的最小距离。

代码实现

朴素法

struct Edge { int x, w; }; // x表示出点,w表示权值.
vector<Edge> g[N]; //存图数组
int dist[N]; //d[i]表示st距离i点的距离大小
void dijkstra(int st)
{
	memset(dist, 0x3f, sizeof dist);
	dist[st] = 0;
	bitset<N> vis; // 初始化d数组全部变成无穷大,d[st]即表示与源点的距离为0

	for (int i = 1; i <= n; i++)
	{
		int t = -1;
		for (int j = 1; j <= n; j++)
			if (t == -1 || (!vis[j] && dist[j] < dist[t]))
				t = j; // 找出离源点最近的一个点

		vis[t] = true; // 表示已经拓展过
		// 此时 d[u] 一定是最优的
		for (auto &y : g[t])
			if (!vis[y.x] && d[y.x] > d[t] + y.w)
				d[y.x] = d[t] + y.w;
	}
}

队列 / 堆优化

vector 存图

struct Edge
{
	int x, w; // x表示出点,w表示权值.
	bool operator < (const Edge &u) const { return w > u.w; }
};
vector<Edge> g[N];
int dist[N];
void dijkstra(int st)
{
	memset(dist, 0x3f, sizeof dist);
	dist[st] = 0;
	bitset<N> vis; // 初始化
	priority_queue<Edge> heap;
	heap.push({st, dist[st]}); // 将源点加入队列

	while (heap.size())
	{
		int t = heap.top().x;
		heap.pop();

		if (vis[t]) continue;
		vis[t] = true;

		for (auto &y : g[t])
		{
			if (!vis[y.x] && dist[y.x] > dist[t] + y.w) // 如果vis[y]则说明y点已经被拓展到最优解,无需更新
			{
				dist[y.x] = dist[t] + y.w; // y点目前仍然不是最优的,不可以进行拓展
				heap.push({y.x, dist[y.x]}); // 将y点加入队列中
			}
		}
	}
}

链式前向星

struct Edge
{
	int ver, val;
	bool operator < (const Edge &rhs) const { return val > rhs.val; }
};

int n, m, st;
int h[N], e[M], ne[M], w[M], idx;
int dist[N];
bool vis[N];
void dijkstra(int st)
{
	priority_queue<Edge> heap;
	memset(dist, 0x3f, sizeof dist), memset(vis, 0, sizeof vis);
	dist[st] = 0;
	heap.push({st, 0});
	
	while (!heap.empty())
	{
		auto [ver, val] = heap.top(); heap.pop();
		
		if (vis[ver]) continue;
		vis[ver] = true;
		
		for (int i = h[ver]; ~i; i = ne[i])
		{
			int to = e[i];
			if (dist[to] > dist[ver] + w[i])
			{
				dist[to] = dist[ver] + w[i];
				heap.push({j, dist[j]});
			}
		}
	}
}
posted @   ThySecret  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示