大厂真题 / 华为

华为 4.22 笔试真题 - AI岗

本场考试概述

考试时间:2026年4月22日 考试岗位:AI岗(国内) 难度评级:困难

考点分析

  1. 选择题(20道):大模型(RAG/分布式训练/推理优化/多模态)、深度学习(Transformer/反向传播/模型部署)、机器学习(评价指标/聚类/距离度量)、数学(线代/数值计算/概率统计)
  2. 第一题:DFS + 前缀和 + 哈希表(难度中等)
  3. 第二题:图建模 + DAG 动态规划(难度困难)

建议策略

  1. 选择题大模型方向题量约占 40%,是华为 AI 岗的核心考点,需重点准备分布式训练、KV Cache、Attention 机制
  2. 第一题是经典前缀和套路在树上的变体,掌握”哈希表 + DFS”模板即可
  3. 第二题分三步:建邻接矩阵 → 筛关键节点 → DAG 最长路 DP,读清楚题意是关键

选择题(20道)

第1题

某运营商构建网络配置命令、设备运行日志、故障案例一体化检索系统,文本中包含大量命令行(如 display interface、ip route)、MAC/IP 地址、端口编号、VLAN ID、OID 等结构化内容。最合适的处理方式是?

A. 对命令行、IP、MAC、端口等增加专用词表,按命令块/日志条目切分,使用通信领域微调 Embedding B. 全部文本统一小写并去除符号,避免分词异常 C. 直接按固定长度切分,使用通用分词与通用 Embedding D. 只使用关键词 BM25 检索,不使用 Embedding

答案:A

考点:大模型——RAG/检索增强

通信领域文本包含大量专用术语(命令行、MAC 地址、OID 等),通用分词会将其错误拆分或忽略。需要增加专用词表保留完整语义,按命令块/日志条目做语义切分,并使用领域微调 Embedding 来捕获专业语境。B 项去除符号会丢失关键信息(如 IP 地址中的点号),C 项固定长度切分会截断命令块,D 项纯 BM25 无法处理语义相似但文本不同的查询。

第2题

在大模型指令微调实验中,研究人员对比了 3 种训练数据配比(纯指令、指令+多轮对话、指令+知识)下的模型响应准确率,需直观展示不同配比的准确率差异并便于组间对比,最适合的可视化图表是?

A. 分组柱状图 B. 雷达图 C. 饼图 D. 直方图

答案:A

考点:机器学习——数据可视化

分组柱状图最适合展示少量分类变量之间的数值对比,3 种配比作为分组、准确率作为柱高,组间差异一目了然。饼图适合展示占比而非对比,雷达图适合多维度评估,直方图用于展示连续变量的频率分布。

第3题

牛顿迭代法的迭代公式为?

A. $x_{n+1} = x_n - \frac{f(x_n)}{f’(x_n)}$ B. $x_{n+1} = x_n - f(x_n)$ C. $x_{n+1} = x_n + \frac{f(x_n)}{f’(x_n)}$ D. $x_{n+1} = \frac{f’(x_n)}{f(x_n)}$

答案:A

考点:数学——数值计算

牛顿迭代法通过在当前点做切线逼近零点,切线方程为 $y = f(x_n) + f’(x_n)(x - x_n)$,令 $y = 0$ 解出 $x_{n+1} = x_n - \frac{f(x_n)}{f’(x_n)}$。C 项符号错误,B 项缺少导数项,D 项分子分母颠倒。

第4题

张量并行(TP)主要用于解决单卡显存无法容纳单个模型层权重的问题,其切分逻辑是?

A. 按优化器状态切分,不同 GPU 维护不同的优化器状态 B. 按网络层深度切分,不同层放在不同 GPU 上 C. 按批次大小切分,不同样本放在不同 GPU 上 D. 按矩阵运算的维度切分,同一层内的权重被拆分到不同 GPU 上

答案:D

考点:大模型——分布式训练

张量并行(Tensor Parallelism)的核心是将同一层的权重矩阵按行或列维度切分到多个 GPU 上,每个 GPU 计算部分矩阵乘法后通过 AllReduce 汇聚结果。A 项描述的是 ZeRO 优化器,B 项是流水线并行(Pipeline Parallelism),C 项是数据并行(Data Parallelism)。

第5题

下列哪个矩阵一定是可逆的?

A. 对称矩阵 B. 行列式为零的矩阵 C. 单位矩阵 D. 所有元素都为零的矩阵

答案:C

考点:数学——线性代数

单位矩阵 $I$ 的行列式为 $1$,且 $I^{-1} = I$,因此一定可逆。对称矩阵不一定可逆(如零矩阵就是对称的),行列式为零的矩阵定义上不可逆,零矩阵行列式为零也不可逆。

第6题

在多轮对话推理系统中,如果 GPU/NPU 显存已满但仍有新的 token 需要生成,系统通常采用什么策略?

A. 将部分 KV Cache swap 到 CPU 或进行 recomputation B. 自动降低模型精度 C. 重启服务器 D. 直接杀掉进程

答案:A

考点:大模型——推理优化

vLLM 等推理引擎在显存不足时,会将低优先级请求的 KV Cache 换出(swap)到 CPU 内存,或在需要时重新计算(recomputation),这是 PagedAttention 的核心机制之一。B/C/D 都不是正常的显存管理策略。

第7题

在部署阶段,将卷积层(Conv)与批归一化层(BN)进行融合(Folding)是各大编译器的标配操作。以下关于 Conv+BN 融合的描述中,最准确的是?

A. 融合是为了让 BN 的梯度能更快反向传播到 Conv 层,从而加速推理 B. 融合是一种纯代数等价变换,在模型编译期(Offline)就将 BN 的缩放和偏移参数直接吸收到 Conv 的权重和偏置中,运行时完全没有 BN 的开销 C. 融合是在运行时(Runtime)将 BN 的均值和方差传入 Conv 的底层算子中并行计算 D. Conv+BN 融合会轻微改变模型的输出精度,因为融合后的算子无法使用 Tensor Core 加速

答案:B

考点:深度学习——模型部署

Conv+BN 融合在编译期完成,将 BN 的 $\gamma, \beta, \mu, \sigma$ 代数合并到 Conv 的权重 $W$ 和偏置 $b$ 中,推理时仅需执行一次卷积操作,消除 BN 的额外计算和显存开销。A 项混淆了训练和推理阶段,C 项并非运行时操作,D 项的精度说法不成立。

第8题

在流水线并行(Pipeline Parallel)中,一个模型被切分为多个 Stage,分布在不同 GPU 上。当某些 GPU 在等待上游 Stage 的计算结果时出现空闲,这种现象被称为?

A. Pipeline Bubble B. 显存碎片 C. GPU Context Switch D. 网络拥塞

答案:A

考点:大模型——分布式训练

Pipeline Bubble 是流水线并行中的核心问题:由于各 Stage 之间存在数据依赖,部分 GPU 在等待上游输出时处于空闲状态,形成”气泡”。GPipe 通过 micro-batch 切分、1F1B 调度等方法来减小 bubble 比例。

第9题

在层次聚类分析(HAC)中,以下哪一种方法是用于定义簇间距离的常见方式?

A. Expectation-Maximization B. K-means C. DBSCAN D. Complete Linkage

答案:D

考点:机器学习——聚类

Complete Linkage(全链接)是层次聚类中定义簇间距离的标准方法之一,取两个簇中最远点对的距离作为簇间距离。同类方法还有 Single Linkage(最近点对)和 Average Linkage(平均距离)。A 是 GMM 的训练算法,B/C 是其他聚类方法,不属于簇间距离的定义方式。

第10题

某多分类任务中,类别 A 有 1000 个样本,类别 B 有 10 个样本。若使用 Micro-F1 计算,主要反映的是哪个类别的性能?

A. 两者权重相同 B. 取决于具体的 F1 计算公式 C. 类别 B D. 类别 A

答案:D

考点:机器学习——评价指标

Micro-F1 将所有类别的 TP/FP/FN 汇总后统一计算 Precision 和 Recall,样本数多的类别贡献更大。类别 A 有 1000 个样本远超类别 B 的 10 个,因此 Micro-F1 主要反映类别 A 的性能。如果需要平等对待各类别,应使用 Macro-F1(对每个类别的 F1 取算术平均)。

第11题

在 PyTorch 中,以下哪个函数用于执行优化器的一步更新?

A. optimizer.zero_grad() B. optimizer.backward() C. optimizer.step() D. optimizer.update()

答案:C

考点:深度学习——PyTorch

PyTorch 训练三步曲:optimizer.zero_grad() 清零梯度 → loss.backward() 计算梯度 → optimizer.step() 根据梯度更新参数。A 项用于清零梯度,B 项不存在(backward 是 tensor 的方法),D 项不是 PyTorch 标准 API。

第12题

工程师需要计算一个复杂函数在某区间上的定积分。以下关于蒙特卡洛积分与黎曼积分的对比,说法正确的是?

A. 蒙特卡洛积分仅适用于低维积分问题,高维时应使用黎曼积分 B. 蒙特卡洛积分的收敛速度为 $O(N^{-2})$,黎曼积分为 $O(N^{-1/2})$ C. 蒙特卡洛积分的计算复杂度远低于黎曼积分,因此总是首选 D. 蒙特卡洛积分的收敛速度为 $O(N^{-1/2})$,黎曼积分(等距划分)为 $O(N^{-2})$

答案:D

考点:数学——数值计算

蒙特卡洛积分基于大数定律,收敛速度为 $O(N^{-1/2})$,与维度无关,这是其在高维积分中的优势。黎曼积分(等距划分,复合梯形法则)在一维下收敛速度为 $O(N^{-2})$,但高维时采样点数呈指数增长(维度灾难)。A 项说反了,B 项两个速度对调了,C 项”总是首选”过于绝对。

第13题

适合高维稀疏向量相似度计算的是?

A. 余弦相似度 B. 切比雪夫距离 C. 欧氏距离 D. 曼哈顿距离

答案:A

考点:机器学习——距离度量

高维稀疏向量中大量维度为零,余弦相似度只关注非零维度的方向一致性,不受向量模长和零值维度影响,是文本检索(TF-IDF、BoW)等高维稀疏场景的标准选择。欧氏距离和曼哈顿距离在高维稀疏空间中区分度下降,切比雪夫距离只看最大差异维度,信息利用不充分。

第14题

Transformer 的编码器-解码器注意力(Encoder-Decoder Attention)中,查询(Query)来自哪里?

A. 输入序列 B. 解码器的上一层的输出 C. 位置编码 D. 编码器的输出

答案:B

考点:深度学习——Transformer

在 Encoder-Decoder Attention 中,Query 来自解码器当前层的上一层输出,Key 和 Value 来自编码器的最终输出。这样解码器的每个位置都能”关注”到编码器的所有位置,实现源语言到目标语言的对齐。

第15题

给定两个向量 $\vec{a}$ 和 $\vec{b}$,它们的余弦相似度为?

A. 1.0 B. 0.87 C. 0.97 D. 0.67

答案:C

考点:数学——线性代数

余弦相似度公式为 $\cos\theta = \frac{\vec{a} \cdot \vec{b}}{\lvert\vec{a}\rvert \cdot \lvert\vec{b}\rvert}$,代入原题给出的具体向量值计算得 $0.97$。余弦相似度衡量两个向量方向的一致性,取值范围为 $[-1, 1]$,$1$ 表示完全同向,$-1$ 表示完全反向,$0$ 表示正交。

第16题(多选)

多模态大模型中,常见的视觉-语言连接器(Connector)包括?

A. MLP(多层感知机) B. 线性投影层(Linear Projection) C. 卷积池化层 D. Q-Former

答案:A, B, D

考点:大模型——多模态

A 正确,LLaVA 使用 MLP 将视觉特征映射到语言空间。B 正确,线性投影是最简单的连接方式,多个模型采用。D 正确,BLIP-2 提出的 Q-Former 通过可学习查询向量从视觉编码器中提取定长特征。C 卷积池化层不是主流的视觉-语言连接器架构,它更多用于视觉编码器内部的特征提取阶段。

第17题(多选)

适用于机器学习中度量两个特征向量的相似度的有?

A. 欧氏距离 B. 余弦相似度 C. 汉明距离 D. KL 散度

答案:A, B, C

考点:机器学习——距离度量

A 正确,欧氏距离是最常用的向量距离度量。B 正确,余弦相似度衡量方向一致性,广泛用于文本和推荐系统。C 正确,汉明距离用于二进制/离散特征向量的比较(如局部敏感哈希)。D 不正确,KL 散度用于度量两个概率分布之间的差异,不是特征向量的相似度指标,且不满足对称性和三角不等式。

第18题(多选)

设 $X_1, X_2, \ldots, X_n \sim N(\mu, \sigma^2)$,下面正确的有?

A. $\mu$ 的 MLE 是样本均值 $\bar{X}$ B. $\mu$ 的 MLE 是无偏的 C. $\sigma^2$ 的 MLE 是 $\frac{1}{n}\sum_{i=1}^{n}(X_i - \bar{X})^2$ D. $\sigma^2$ 的 MLE 是无偏的

答案:A, B, C

考点:数学——概率统计

A 正确,对正态分布的对数似然求导令其为零,$\hat{\mu} = \bar{X}$。B 正确,$E[\bar{X}] = \mu$,样本均值是 $\mu$ 的无偏估计。C 正确,$\hat{\sigma}^2 = \frac{1}{n}\sum(X_i - \bar{X})^2$。D 不正确,$E[\hat{\sigma}^2] = \frac{n-1}{n}\sigma^2$,MLE 方差估计是有偏的,无偏版本需除以 $n-1$。

第19题(多选)

以下关于反向传播计算效率的说法正确的是?

A. 反向传播的计算量大约是前向传播的 2 倍 B. 符号微分跟数值微分是两种计算体系,在一个模型训练时只能使用其中一种 C. 反向传播需要存储所有中间层的激活值,因此显存消耗大 D. 相比于数值微分,符号微分计算梯度的速度快

答案:A, C

考点:深度学习——反向传播

A 正确,反向传播对每个算子需要计算其所有输入的梯度,计算量约为前向传播的 2 倍(经验值)。C 正确,反向传播依赖链式法则,需要保存前向过程中各层的激活值用于梯度计算,这是显存消耗的主要来源(梯度检查点技术可缓解)。B 不正确,深度学习实际使用的是自动微分(AD),并非严格的符号微分或数值微分,且两者并非互斥。D 不正确,符号微分会产生表达式膨胀(expression swell),对于深层网络反而可能更慢。

第20题(多选)

你维护的在线问答服务(vLLM)在晚高峰出现:TTFT 从 0.9s 升至 2.4s,decode tokens/s 基本不变,平均输入长度从 700 升至 2200,GPU 利用率接近满载。你本班次可立即执行哪些动作?

A. 对超长输入先走”摘要压缩链路”,再送主模型 B. 增大 temperature 到 1.2 C. 把 max_new_tokens 从 512 调到 1024 D. 开启/优化 prefix cache(固定 system prompt 场景)

答案:A, D

考点:大模型——推理优化

TTFT(Time To First Token)飙升但 decode 速度不变,说明瓶颈在 prefill 阶段,输入变长导致 prefill 计算量剧增。A 正确,对超长输入先做摘要压缩,缩短实际送入模型的序列长度,直接降低 prefill 计算量。D 正确,开启 prefix cache 可以复用固定 system prompt 的 KV Cache,避免重复计算。B 不正确,temperature 只影响采样策略,不改善 TTFT。C 不正确,增大 max_new_tokens 只会延长 decode 阶段,对 TTFT 没有帮助反而加重负载。


第一题:统计二叉树中平衡路径的数量

题目描述

定义二叉树的平衡路径需同时满足以下条件:

  1. 路径从任意节点出发,仅能向下延伸(只能向左/右子节点,不可向上回溯)
  2. 路径上所有节点的值相加为 $0$
  3. 路径长度(包含的节点个数)至少为 $2$

输入二叉树的层序遍历列表(元素为整数或 None),返回该树中所有平衡路径的总数。

建树规则:层序遍历列表按从上到下、从左到右的顺序构建二叉树,None 表示对应位置无节点。路径只沿左子节点或右子节点单向向下(单链,不可分叉)。每个符合条件的单链路径独立计数。列表长度 $\leq 10000$,节点值范围 $[-1000, 1000]$。

样例

输入

[10, -5, -5, 2, -2, 3, -3]

输出

0

输入

[0, 0, None]

输出

1

输入

[1, -1, 2, -2, None, 3, -3]

输出

2

思路分析

第一步:暴力法为什么太慢

最直接的做法是枚举每个起点、枚举每个终点、算路径和。对每条链来说,起点有 $O(n)$ 个,每个起点往下的路径长度也是 $O(n)$,暴力是 $O(n^2)$。前缀和技巧可以把”算路径和”变成”查一次表”,一趟 DFS 就能搞定。

第二步:层序数组就是隐式二叉树

输入数组按层序排列,索引 $i$ 的左孩子在 $2i + 1$,右孩子在 $2i + 2$。不需要真正建树,直接用数组下标就能知道谁是谁的孩子。

第三步:前缀和的核心思想

从根节点出发一路向下走到某个节点 $v$,沿途所有节点值的累加就是 $v$ 的前缀和 $\text{pre}(v)$。想知道从祖先 $u$ 到后代 $v$ 这段路径的和,不用重新加,直接用:

\[\text{路径和} = \text{pre}(v) - \text{pre}(u \text{ 的父节点})\]

这和数组前缀和的思路完全一样——大段减去小段等于中间那段。

第四步:什么时候路径和为零

路径和为零意味着 $\text{pre}(v) = \text{pre}(u \text{ 的父节点})$。换句话说,如果当前节点的前缀和等于路径上某个祖先的”父前缀和”,那从这个祖先到当前节点的路径和就是 $0$。

用哈希表 counts 记录”从根到当前节点路径上,每个前缀和值出现了几次”。走到节点 $v$ 时算出 $\text{pre}(v)$,查 counts[pre(v)] 就知道有几条和为零的路径以 $v$ 结尾。

初始往表里放一个 $\text{counts}[0] = 1$,代表根的上方有一个”虚拟节点”(前缀和为 $0$),这样从根开始的全路径也能被匹配到。

第五步:节点值为 0 时的特殊处理

题目要求路径至少包含 $2$ 个节点。当节点值为 $0$ 时,它的前缀和等于父节点的前缀和,哈希表会把”只有自己”这条长度为 $1$ 的路径也匹配进去。这条不合法,查到的计数要减 $1$。

第六步:回溯——进子树前加、出子树后减

进入子树前把当前前缀和加入哈希表,从子树返回后减掉。如果不减,左子树残留的值会影响右子树的查询——右子树会”看到”左子树里根本不在同一条链上的祖先。

题解代码

import sys
from collections import defaultdict

sys.setrecursionlimit(20000)
input = sys.stdin.readline

line = input().strip()
start = line.index('[')
end = line.rindex(']')
content = line[start + 1:end]
tokens = content.split(',')

nodes = []
is_null = []
for t in tokens:
    t = t.strip()
    if t == 'None' or t == '':
        nodes.append(0)
        is_null.append(True)
    else:
        nodes.append(int(t))
        is_null.append(False)

n = len(nodes)
result = 0
counts = defaultdict(int)
counts[0] = 1

def dfs(idx, prefix_sum):
    global result
    if idx >= n or is_null[idx]:
        return
    prefix_sum += nodes[idx]
    cnt = counts[prefix_sum]
    if nodes[idx] == 0:
        cnt -= 1
    result += cnt
    counts[prefix_sum] += 1
    dfs(2 * idx + 1, prefix_sum)
    dfs(2 * idx + 2, prefix_sum)
    counts[prefix_sum] -= 1

dfs(0, 0)
print(result)

复杂度分析

时间复杂度:$O(n)$,DFS 每个非空节点访问一次,每次哈希表操作 $O(1)$ 空间复杂度:$O(h)$,$h$ 为树的深度,哈希表最多同时存 $h$ 个前缀和


第二题:网络异常流量传播链路溯源

题目描述

在网络监控中,异常流量的流动通常具有局部聚集性。需要识别出高负载的基站(关键节点),并判断流量在这些节点之间定向传播链的最长路径。

给定 $N$ 个基站,每个基站有坐标 $(x_i, y_i)$、时间戳 $t_i$、负载 $w_i$ 和用户数 $u_i$。规则如下:

  • 直接关联:两个基站的曼哈顿距离 $\lvert x_i - x_j \rvert + \lvert y_i - y_j \rvert \leq \varepsilon$ 则关联
  • 关键节点:一个基站及其所有关联基站(含自身)的负载之和 $\geq W$ 则为关键节点
  • 链路条件:两个关键节点直接关联且时间戳不同,流量从时间早的流向时间晚的;时间相同则无法建立链路
  • 传播链条:由一系列关键节点通过有向链路首尾相连构成的路径,链条规模为路径上所有节点的用户数 $u$ 之和

计算全网中所有传播链条能覆盖的最大用户总数。若无法形成任何传播链条(至少 $2$ 个节点),输出 $0$。

输入第一行为 $N$、$\varepsilon$、$W$,接下来 $N$ 行每行为 $x_i\ y_i\ t_i\ w_i\ u_i$。

样例

输入

3 1 500
0 0 10 100 50
1 0 20 100 50
0 1 30 100 50

输出

0

输入

4 1 150
0 0 10 100 10
1 0 20 100 10
5 5 10 200 100
5 6 30 200 100

输出

200

思路分析

这道题分两半:前半段是预处理——按规则筛关键节点,后半段才是算法核心——在关键节点上做 DP 找最优链。

第一步:建邻接矩阵

$N \leq 1000$,两层 for 循环检查所有基站对的曼哈顿距离是否 $\leq \varepsilon$,用一个二维布尔数组 adj[i][j] 记录关联关系。$O(N^2)$ 完全够快。

第二步:筛选关键节点

对每个基站 $i$,把自己的负载加上所有关联邻居的负载,如果总和 $\geq W$ 就标记为关键节点。

以样例 1 为例:3 个基站两两关联(距离都 $\leq 1$),每个基站的邻域负载和为 $100 + 100 + 100 = 300 < 500$,没有关键节点,输出 $0$。

以样例 2 为例:基站 0 和基站 1 关联(距离 $1$),基站 2 和基站 3 关联(距离 $1$)。基站 2 的邻域负载和为 $200 + 200 = 400 \geq 150$,基站 3 同理,所以基站 2 和 3 是关键节点。

第三步:DAG 最长路 DP

流量只能从时间早的基站传向时间晚的,不会折返。将关键节点按时间从小到大排序,就得到了 DAG 的拓扑序。

定义 $f[j]$ 为传播链的最后一站是第 $j$ 个关键节点时,链上所有节点的用户数之和的最大值。初始每个节点独立成链,$f[j] = u_j$。

按时间顺序从前往后处理每个节点 $j$,回头看排在前面的每个节点 $i$:如果 $i$ 和 $j$ 关联且时间严格递增,则 $f[j] = \max(f[j],\ f[i] + u_j)$。

最终答案只统计被边更新过的 $f[j]$(即链上至少 $2$ 个节点)。

题解代码

import sys

input = sys.stdin.readline

line = input().split()
N, eps_dist, w_threshold = int(line[0]), int(line[1]), int(line[2])

stations = []
for _ in range(N):
    parts = list(map(int, input().split()))
    stations.append(parts)

adj = [[False] * N for _ in range(N)]
for i in range(N):
    for j in range(i + 1, N):
        dist = abs(stations[i][0] - stations[j][0]) + abs(stations[i][1] - stations[j][1])
        if dist <= eps_dist:
            adj[i][j] = True
            adj[j][i] = True

is_key = [False] * N
for i in range(N):
    total_w = stations[i][3]
    for j in range(N):
        if i != j and adj[i][j]:
            total_w += stations[j][3]
    if total_w >= w_threshold:
        is_key[i] = True

key_nodes = [i for i in range(N) if is_key[i]]
key_nodes.sort(key=lambda i: stations[i][2])

m = len(key_nodes)
f = [stations[key_nodes[i]][4] for i in range(m)]

ans = 0
for j in range(m):
    nj = key_nodes[j]
    for i in range(j):
        ni = key_nodes[i]
        if adj[ni][nj] and stations[ni][2] < stations[nj][2]:
            f[j] = max(f[j], f[i] + stations[nj][4])
            ans = max(ans, f[j])

print(ans)

复杂度分析

时间复杂度:$O(N^2)$,建邻接矩阵和 DP 转移各 $O(N^2)$ 空间复杂度:$O(N^2)$,主要是邻居关系的二维数组


小结

  • 选择题大模型方向占比约 40%(RAG、张量并行、Pipeline Bubble、KV Cache swap、prefix cache、多模态连接器、Conv+BN 融合),是华为 AI 岗的绝对核心考点
  • 第一题是 LeetCode 437「路径总和 III」的变体,核心是”前缀和 + 哈希表 + DFS 回溯”的组合拳。注意节点值为 $0$ 时要排除长度为 $1$ 的路径
  • 第二题的难度主要在读题和建模,算法本身只是 DAG 最长路 DP。关键是分清三个步骤:建邻接矩阵 → 筛关键节点 → 按时间排序后 DP