跳转至

D. Hyperlane Hopper

分数:150 分

“在那无穷的星辰大海中,最近的路往往不是直线,而是过路费最少的那条。” —— 银河联邦导航员手册,第 42 章

背景

公元 30777 年,人类文明实现了银河系的互通,连接这些星系的是一种被称为 "Hyperlane" 的古老网络。每条航道连接两个星系,由于引力波动、空间碎片以及道路维护费不同,每条航道的通行代价都是不一样的,且均为非负整数。

你作为银河速运的首席算法架构师,面临着一个严峻的问题:随着双十一的临近,由于订单量暴涨,从人类文明早期传承下来的单线程导航核心(基于古老的 Dijkstra 算法)已经无法在客户失去耐心前规划出最短路径。因为系统还运行在 30000 年前构建的服务器上(没有人敢动),无法使用高效的量子计算资源。好在你从地球南极挖出了 github 保存的 16 核 CPU 服务器,准备将导航系统升级为多线程版本,以提升路径规划的效率。至于其他部分,那就期待后人的智慧吧。

任务描述

本题是一个经典的单源最短路 (Single Source Shortest Path, SSSP) 问题。给定一个包含 n 个节点和 m 条边的有向图 G=(V, E),边的权重 w \ge 0

你可以使用任何算法来解决这个问题,只要最终结果正确即可。建图部分也可以优化。

输入输出

本题中输入输出函数 main.cpp已经为你实现,它会调用sssp.cpp中的calculate函数,函数原型如下。不过我们仍然在此处说明输入输出格式以便参考。你可以在handout目录下找到main.cpp 的实现。

void calculate(uint32_t n, uint32_t m, uint32_t *edges, uint64_t *dis)

输入

程序接受三个参数,nmseed,分别表示节点数、边数和随机数种子。程序会根据这些参数生成一个有向图。

输出

程序输出一个二进制文件,文件名是 dis.bin,其中包括 n 个 64 位无符号整数,第 i 个整数表示从源点 0 到节点 i 的最短路径长度。如果节点不可达,输出0xFFFFFFFFFFFFFFFF。保证输出不会溢出uint64_t 的范围。

运行环境、编译与测试

本题将在 Intel Xeon Platinum 8358 CPU 的 16 核心环境下运行。

评测容器镜像:cr.hpc.lcpu.dev/hpcgame/base:latest,基础发行版为Rocky Linux 10.1。编译命令如下。我们在 handout 里提供了一个Makefile,你也可以直接使用下面的命令编译:

g++ -O3 -std=c++20 -flto -march=native -fopenmp -pthread -o sssp main.cpp sssp.cpp

我们会这样运行:

export OMP_NUM_THREADS=16
export OMP_PLACES=cores
export OMP_PROC_BIND=close
./sssp n m seed

评测

所有结果必须正确,否则不得分。

数据可能存在重边和自环。数据保证所有点可达。

对于所有测试点,边长随机分布在 [1, 10^7]。所有图都是随机图,dis已初始化,具体详见main.cpp

每个测试点得到正确结果获得基本分数,性能分数与运行时间倒数成正比。

final_score = correct? base_score + perf_score * min(goal / time, 1): 0

n m base score perf score limit goal
1e5 2e5 10 10 0.03 s 0.005 s
1e5 1e7 5 15 1 s 0.06s
1e6 2e8 5 5 20 s 1.2s
1e6 1e9 5 5 100 s 5.5s
1e7 1e7 0 10 2 s 0.2s
1e7 2e7 0 15 5 s 0.35s
1e7 1e8 0 15 17 s 1.4s

附件