zoukankan      html  css  js  c++  java
  • 2019.8.4刷题统计

    第一题: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(一定要用堆优化)。

  • 相关阅读:
    ndarray转PIL
    215. 数组中的第K个最大元素
    pytorch的分布式
    剑指 Offer 06. 从尾到头打印链表
    最长公共子序列
    剑指 Offer 57
    剑指 Offer 59
    剑指 Offer 48. 最长不含重复字符的子字符串
    Python线程池
    Python 常用内置函数
  • 原文地址:https://www.cnblogs.com/wangximing/p/11298481.html
Copyright © 2011-2022 走看看