[OO] JML系列 优化及时间复杂度可行性证明

JML系列 优化及时间复杂度可行性证明

符号定义

符号 意义 上限
p p 网络中Person数量 800
r r 网络中关系数量 3000
q s q_s 查询queryStrongLinked数量 20
q r q_r 查询queryNameRank数量 1000
q b q_b 查询queryBlockSum数量 3000
q a q_a 查询queryAgeSum数量 3000
q m q_m 查询queryMinPath数量 3000

优化方法与复杂度分析

queryBlockSum

  • 由于不需要删除操作,故采用并查集实现
  • 并查集单次操作的均摊复杂度为 O ( α ( n ) ) O(\alpha(n)) ,其中 α \alpha 为一个Ackerman函数相关的,这里可以认为小于常数 4 4
  • 每次查询时需遍历每个Person,时间复杂度 O ( α p ) O(\alpha p)
  • 动态维护加边的复杂度 O ( α r ) O(\alpha r)
  • 总时间复杂度 O ( α p q b + α r ) O(\alpha p q_b+\alpha r) 上限小于 1 × 1 0 7 1\times10^7 ,稳妥

queryAgeSum

  • 采用直接暴力枚举Person进行计数的方法
  • 时间复杂度为 O ( q a p ) O(q_a p) ,上限 2.4 × 1 0 6 2.4\times10^6 ,稳妥

queryNameRank

  • 采用每次查询直接暴力统计的方法
  • 时间复杂度 O ( q r p ) O(q_r p) ,上限 8 × 1 0 5 8\times10^5 ,稳妥

queryMinPath

  • 采用堆优化Dijkstra算法,因为不需要处理负环
  • 单次单源最短路径时间复杂度 O ( ( p + r ) l o g r ) O((p+r)logr)
  • 总体时间复杂度为 O ( q m ( p + r ) l o g r ) O(q_m (p+r)logr) ,上限较大,但由于总指令数限制,还满足关系 q m + p + r 3000 q_m+p+r\le3000 ,求极值可估计真实复杂度上限小于 2.5 × 1 0 7 2.5\times10^7
  • 注意此题不写堆优化上限可达 1 × 1 0 9 1\times10^9 大概率被卡
  • 另外spfa已死,不卡是情分,卡是本分,参考NOI2018Day1T1,这本来也是一种及其不稳定的算法

queryStrongLinked

暴力枚举

  • 这种做法需要两步bfs/dfs
  • 第一次判断连通后,枚举去掉所有割点再次bfs判断是否仍然联通,如果都能联通,说明这两个点点双连通
  • 这里的枚举割点是准确条件,但实现的时候如果不想再写一个找割点的算法(还是Tarjan),可以用枚举所有点替代
  • 第二次bfs采用MASK的方法加速,不需要修改原图
  • 总时间复杂度 O ( q s p ( p + r ) ) O(q_s p(p+r)) 时间复杂度上限可达 4.8 × 1 0 7 4.8\times10^7 ,应该能过,但有些小小的危险,如果具体实现太丑有可能被卡常,不过相信课程组是善良的
  • 【更新】:经大佬指点,发现只需要MASK第一次bfs找到的路径上的非首尾点,原因在于双连通是为了找第二条除首尾外无重复节点的路径,MASK第一条路径后如果还能连通,那么必然双连通,复杂度降低为 O ( 2 q s ( p + r ) ) O(2q_s (p+r)) ,上限在 1.2 × 1 0 5 1.2\times10^5 稳妥地过!

点双连通分量

  • 大致思路采用Tarjan找点双连通分量,再判断两个点是否具有相同编号(只是大致思路)
  • 单次Tarjan就是dfs的复杂度 O ( p + r ) O(p+r)
  • 判断是否双连通复杂度 O ( p ) O(p)
  • 时间复杂度 O ( q s ( 2 p + r ) ) O(q_s (2p+r)) 上限小于 1 × 1 0 5 1\times10^5 稳妥
  • 需要注意这种做法一定要多做测试!!!

其他

  • 前两次作业的此处省略,没必要写的也省略
  • 如有错误还请指正
原创文章 152 获赞 15 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ourfutr2330/article/details/106118364