ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2019.8.4刷题统计

2019-08-04 16:05:15  阅读:904  来源: 互联网

标签:算法 2019.8 复杂度 SPFA Dijkstra 这道题 代码 统计 刷题


第一题:1105

这道题极其简单。

AC代码:

第二题:1106

这道Dijkstra的模板题我竟然提交了三遍才过。但我的错误并不在Dijkstra里面,而是在主程序中的一些细节。

第一次提交:

看到上面红圈中的内容,就可以知道这份代码一定是会超时的了。

Dijkstra函数在每一次计算中都重复调用了2(p-1)次!

Dijkstra算法的时间复杂度是O(边数log2点数),所以我的代码时间复杂度就是O(n*2p*log2(p)*q),虽然n的数据范围没有给出,但是光是一个p*q的时间复杂度就接受不了(最大是2*1012),再乘上n和log2(p),大概就达到1014级别的复杂度了。

而这个上面程序中的算法有一个非常明显的优化:Dijkstra执行一遍可以知道一个点到其它所有点的距离,这样的话在循环中就只需要执行一次Dijkstra算法了。如果这样,时间复杂度会降为O(n*p*log2(p)*q),但这样优化只不过是一个常数优化,复杂度仍然只是比1014级别低一点的。

这个算法还可以以类似的形式继续优化:如果反向建边,那么从结点1~所有其他节点的最短路长度之和=原来没有反向建边时所有结点~结点1的最短路之和。

这样时间复杂度变为O(n*log2(p)*q),理论上时间复杂度可能是108,但是n一般不会很大,所以在107就能跑过了。

贴上第二份代码:

这份代码虽然在给定时间内执行完了,但是却还是错误的。

而这份代码的错误原因非常低级——竟然是因为没有初始化!

有些人可能认为外循环每执行一次进行一次clear或memset就行了,对于一般程序这样可以,但在这个程序中外循环每执行一次,Dijkstra算法却执行了两次,所以需要初始化两次(或者在函数中初始化也行)。

AC代码:

虽然这份代码不是最优的(比如可以在Dijkstra函数中初始化v数组),但它绝对是没问题的。

这道题标题上写着可以用SPFA和Dijkstra两种算法做,虽然SPFA很容易被卡(出题人可以专门造几个卡SPFA的数据),而且这道题也没有负边权,更没有负环,不过这道题中的图是一个稀疏图,而且这道题说了可以用SPFA,应该是没问题的。

SPFA的理论复杂度是O(k边数),其中k为常数(每个节点平均入队次数),一般情况下大概在2左右,一般不会超过4。但是如果遇到出题人特意造卡SPFA的数据,k最大可以和点数相等,这个时候SPFA一般就不能通过(在这道题中复杂度为O(k*106),最坏情况下则是(1012))。

这道题用SPFA算法也能AC。

AC代码:

这份代码主程序部分和Dijkstra基本相同,而函数就是SPFA模板,就不再加注释了。这道题中边权都是正的,所以不可能存在负环,就没判断负环。

在这道题中,SPFA算法无论是时间还是空间,都比Dijkstra要差,所以遇到没有负权的题目还是首选Dijkstra(一定要用堆优化)。

标签:算法,2019.8,复杂度,SPFA,Dijkstra,这道题,代码,统计,刷题
来源: https://www.cnblogs.com/wangximing/p/11298481.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有