1. 程式人生 > 實用技巧 >學習記錄:Dijstra最短路

學習記錄:Dijstra最短路

目錄

學習記錄:Dijstra最短路

其實Dijstra早學過,這次主要寫點用鄰接表和堆優化的東西

想法

Dijstra的想法其實很簡單,維護一個已經達到最短路線的點的集合即可。

從出發點開始,找到距離出發點最近的那個點加入集合,重複此步驟直至所有點都加入集合即可。

原因很簡單,設出發點為\(s\),距離\(s\)最近的點是\(i\)\(Dis[i]<Dis[其他點]+其他點到點i的距離\),因此最近的點就加入集合了。

鄰接矩陣實現的Dijstra

最簡單的Dij,但是過不了[洛谷弱化版的模板題][

https://www.luogu.com.cn/problem/P3371],空間佔用大,但是方便理解Dij的思路

int Map[maxn][maxn];
int vis[maxn];
ll dis[maxn];
int n, m, s;
void Dij()
{
	for (int i = 1; i <= n; i++)
		dis[i] = Map[s][i];
	dis[s] = 0;
	vis[s] = 1;
	for (int j = 1; j <= n; j++)
	{
		int flag = 0;
		for (int i = 1; i <= n; i++)
			if (!vis[i] && (dis[i] < dis[flag] || flag == 0))
				flag = i;
		vis[flag] = 1;
		for (int i = 1; i <= n; i++)
			if (!vis[i])
				dis[i] = min(dis[i], dis[flag] + Map[flag][i]);
	}
}
int main()
{
	cin >> n >> m >> s;
	while (m--)
	{
		int u, v, w;
		cin >> u >> v >> w;
		Map[u][v] = min(w, Map[u][v]);//洛谷的資料最坑的就是有重邊...
	}
	Dij();
	for (int i = 1; i <= n; i++)
		cout << dis[i] << ' ';
	return 0;
}

鄰接表實現的Dijstra

這樣就可以過模板題了。用的vector實現。

struct node
{
	int to, val;
	node(int to, int val) : to(to), val(val) {}
};
ll n, m, s;
ll dis[maxn];
int vis[maxn];
vector<node> Map[maxn];
void Dij()
{
	for (int i = 0; i <= n; i++)
		dis[i] = INF;
	dis[s] = 0;//這裡沒有初始化dis陣列,是因為接下來的迴圈可以直接初始化
	for (int k = 0; k < n; k++)
	{
		int kk = 0;
		for (int i = 1; i <= n; i++)
			if (!vis[i] && dis[i] < dis[kk])
				kk = i;
		vis[kk] = 1;
		for (int i = 0; i < Map[kk].size(); i++)
			if (dis[Map[kk][i].to] > dis[kk] + Map[kk][i].val)
				dis[Map[kk][i].to] = dis[kk] + Map[kk][i].val;
	}
}
int main()
{
	cin >> n >> m >> s;
	for (int i = 0, a, b, c; i < m; i++)
	{
		cin >> a >> b >> c;
		Map[a].push_back(node(b, c));
	}
	Dij();
	for (int i = 1; i <= n; i++)
		cout << dis[i] << ' ';
	return 0;
}

堆優化的Dijstra

struct node
{
	int to, val;
	node(int to, int val) : to(to), val(val) {}
};
int n, m, s;
vector<node> Map[maxn];
int vis[maxn], dis[maxn];

typedef pair<int, int> P;
void Dij()
{
	priority_queue<P, vector<P>, greater<P>> q;
	MS(dis, INF);
	dis[s] = 0;
	q.push(P(0, s));
	while (!q.empty())
	{
		P p = q.top();
		q.pop();
		int index = p.second;
		if (dis[index] < p.first)
			continue;
		for (int i = 0; i < Map[index].size(); i++)
		{
			node e = Map[index][i];
			if (dis[e.to] > dis[index] + e.val)
			{
				dis[e.to] = dis[index] + e.val;
				q.push(P(dis[e.to], e.to));
			}
		}
	}
}
int main()
{
	cin >> n >> m >> s;
	for (int i = 1, x, y, z; i <= m; i++)
	{
		cin >> x >> y >> z;
		Map[x].push_back(node(y, z));
	}
	Dij();
	for (int i = 1; i <= n; i++)
		cout << dis[i] << ' ';
	return 0;
}