作为一名蓝桥杯er(今年acm成绩并不理想),还有一个星期,蓝桥杯国赛就要到来,我肯定是希望能够拿到国赛一等奖的,也有可能事与愿违;
总之现在来讲一下常用的Djikstra算法,效率高但是不支持负权,而之前写的bellmanford能够支持负权环,至于能够支持负权环的floyd算法,可能得下次再学;
至于存图结构,我想了一下,邻接表和链式前向星可能差不多,而邻接矩阵太慢,具体可以看这篇文章链式前向星,也可以看我的前一篇文章,总之,链式前向星我认为是一个很好用,很好理解并且很好写的数据结构。
对于最短路算法,我觉得bellmanford算法很像dfs,而Djikstra像bfs,可以看我之前写的DFS和BFS,一个是一直遍历到最内层(尽管“松弛”操作使得循环并不是一次进行到底),另一个则是将每一层单独放进一个队列并且进行遍历,结构上都非常相似(以上是笔者的一些理解,可能有些人学的板子和我的不一样,不要见怪),而且笔者不会制作动图和动态视频,这个资源在网上随便能找到,如果对文字说明还是不能理解的话就去找个视频看看。
存图在这里也不过多赘述,这里直接上代码
vector<ll>dist(n+1,INT_MAX);//1到每个点的距离,初始为无限远
vector<bool>vis(n+1,false);//走过的就不再走,避免重复操作
dist[1]=0;
priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>>pq;
//first是当前的距离,second是当前的节点
pq.push({dist[1],1});//放入第一个元素,进入循环
while(pq.size())
{
ll crrDist=pq.top().first;//这句可以不要,为了规范理解所以保留
ll u=pq.top().second;//本次的起点
pq.pop();
if(vis[u])continue;//如果走过就跳过
vis[u]=true;//标记
for(ll i=head[u];i!=-1;i=edge[i].next)//循环这个节点的每一个子节点
{
dist[edge[i].goal]=min(dist[edge[i].goal],dist[u]+edge[i].value);//松弛
pq.push({dist[edge[i].goal],edge[i].goal});//推入下一个节点
}
}
可见vis数组,以及队列(此处因为要找最短路所以使用小根堆,也可以全部存进队列然后再遍历比较大小,尽管这个操作显得多余且时效性不如优先队列)和BFS的代码如出一辙,只是稍加修改,能够理解代码就说明学会了(
1089

被折叠的 条评论
为什么被折叠?



