图论-最短路-Dijkstra-优化

蒟蒻在上一篇写了Dijkstra的基本思想,现在来讲一下它的优化。首先需要用到一个叫做优先队列以及一个叫邻接表的东西(不懂的话……百度上应该有)
上篇的算法在每次循环中都要用n来找到距离原点最近的点,维护一个小根堆可以完美解决这个问题,注意:如果不用邻接表存储的话,优不优化差不多,剩下的操作就很简单了,把循环的步骤改成:
1.取堆顶作为中转点,如果是蓝点continue
2.枚举与该点相连的每条边,更新最小值
(完美)
下面贴代码

#include<bits/stdc++.h>
using namespace std;
struct dian{
	int name,val;//每个点,存它的编号和距原点的距离,用来维护小根堆 
};
struct edge{
	int l,r,v;//每条边,左端点,右端点和边权 
};
vector<edge> g[1005];
int n,m,s1,s2,dist[1005];
bool operator < (dian a, dian b) {//重载小于号,根据距离来排序,类似于sort的cmp 
    return a.val > b.val;
}
priority_queue<dian> cmp;//小根堆 
void Dijkstra(int x)
{
	bool book[1005];
	memset(book,0,sizeof(book));
	for(int i=1;i<=n;i++)
	{
		dist[i]=INT_MAX;
	}
	while(cmp.size()!=0)
	{
		dian cun;
		cun=cmp.top();cmp.pop();//代替了之前的循环来取离原点最近的白点 
		if(book[cun.name]==1) continue;//如果是蓝点跳过 
		book[cun.name]=1;
		for(int i=0;i<g[cun.name].size();i++)//枚举所有边,更新答案
		{
			dist[g[cun.name][i].r]=min(dist[g[cun.name][i].r],cun.val+g[cun.name][i].v);
			dian lin;
			lin.name=g[cun.name][i].r;
			lin.val=dist[g[cun.name][i].r];
			cmp.push(lin);//把答案扔进堆里 
		}
	}
}
int main()
{
	cin>>n>>m;
	int x,y,z;
	edge lin;
	for(int i=0;i<m;i++)
	{
		cin>>x>>y>>z;
		lin.l=x;
		lin.r=y;
		lin.v=z;
		g[x].push_back(lin);//无向图所以存两次 
		lin.l=y;
		lin.r=x;
		g[y].push_back(lin);
	}
	cin>>s1>>s2;
	dian cun;
	cun.name=s1;
	cun.val=0;
	cmp.push(cun);
	Dijkstra(s1);
	dist[s1]=0;
	cout<<dist[s2];
	return 0;
}

比之前快了好多有木有(写的比较丑不要太在意)

posted @ 2019-07-12 14:15  kirito_raligun  阅读(176)  评论(0编辑  收藏  举报