2021-02-18 Logu P4779dijslralアルゴリズムテンプレート

概要:

ダイクストラのアルゴリズムのヒープ最適化バージョンについて


問題の説明:

詳細については、タイトルを参照してください:Luogu P4779


アルゴリズムの説明:

dijskralアルゴリズムの本質は、欲張り戦略と動的計画法のアイデアを適用します。原理は次のように要約できます。新しく生成された最短パスは、すでに生成された最短パスにエッジを追加することによって生成されます。最初は、開始点sから開始点sまでの距離は0であり、追加される各エッジは、グラフのエッジセットから特定のポイントの隣接するエッジを選択することによって追加されます。

特定の実装では、開始点sからの距離が最短の点uが選択されるたびに、uからsまでの距離が今回選択された最短経路になります。現在の距離sが最短の点uを選択した後、uの隣接点を検討します。つまり、新しく生成された最短経路(point)が、最短経路が生成されない点から開始点までの距離を更新できるかどうかを検討します。 s

要約すると
、開始点sからの距離が最も短い点が選択されるたびに、この点のその他の点への寄与が考慮されます。


詳細なコードとコメント:

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
struct edge{
    
    
	int to;
	int next;
	int w;
};
struct node{
    
    
	int num;
	int d;
	node(int _num = 0, int _d = 0) :num(_num), d(_d) {
    
    }
	bool operator()(const node& n1, const  node& n2)
	{
    
     
		return n1.d > n2.d;//">"表示建立小根堆,"<"表示建立大根堆
	}
};

class Solution{
    
    
public:
	int n, m, s;  //分别为点数,边数,起点
	int cnt = 0;  //记录当前输入到第几条边,用于链式前向星建图
	//链式前向星建图
	vector<int> head;
	vector<edge> e;
	//记录是否已经产生最短路径
	vector<bool> visit;
	//堆优化
	priority_queue<node,vector<node>,node> q;  //自定的变量使用std::堆的方法
	/*
	priority_queue<自定义的结构体的名称,vector<自定的结构体的名称>,自定的结构体的名称> q;
	自定的结构体中必须重载"()"操作符
	*/
	//保存的最终答案
	vector<int> dfs;  //distance from source

	//链式前向星建图模板
	inline void add_edge(int u, int v, int w)
	{
    
    
		cnt++;
		e[cnt].to = v;
		e[cnt].w = w;
		e[cnt].next = head[u];
		head[u] = cnt;
	}

	void dijskral()
	{
    
    
		cin >> n >> m >> s;
		visit.resize(n + 1, false);
		head.resize(n + 1, 0);
		dfs.resize(n + 1, 2147483647);
		e.resize(m + 1);
		for (int i = 1; i <= m; ++i)
		{
    
    
			int u, v, w;
			cin >> u >> v >> w;
			add_edge(u, v, w);
		}
		dfs[s] = 0;
		q.push(node(s,0));
		while (!q.empty())
		{
    
    
			node temp = q.top();
			q.pop();
			int x = temp.num;
			int d = temp.d;
			if (visit[x])
				continue;
			visit[x] = true;
			for (int i = head[x]; i != 0; i = e[i].next)
			{
    
    
				int y = e[i].to;
				if (dfs[y] > dfs[x] + e[i].w)
				{
    
    
					dfs[y] = dfs[x] + e[i].w;
					if (!visit[y])
						q.push(node(y, dfs[y]));
				}
			}
		}
		for (int i = 1; i <= n; ++i)
			cout << dfs[i] << " ";
	}
};


int main() {
    
    
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	Solution s;
	s.dijskral();
}


おすすめ

転載: blog.csdn.net/sddxszl/article/details/113841523