最长交错路径(Longest Alternating Path in a Directed Graph)
字数 5105 2025-12-16 23:58:05

最长交错路径(Longest Alternating Path in a Directed Graph)

题目描述

给你一个有向图,图中有 n 个节点,节点编号从 0 到 n-1。同时给你一个整数数组 values,其中 values[i] 表示节点 i 的值。图中还有 m 条有向边,每条边从节点 u 指向节点 v。

我们定义一个路径为“交错路径”,如果路径上相邻节点的值交替严格递增和严格递减。更形式化地,对于一个节点序列 p0, p1, ..., pk,对于所有满足 0 ≤ i < k 的 i,必须满足以下条件之一:

  • 如果 i 是偶数,则 values[p_i] < values[p_(i+1)](递增)。
  • 如果 i 是奇数,则 values[p_i] > values[p_(i+1)](递减)。
    或者反过来:
  • 如果 i 是偶数,则 values[p_i] > values[p_(i+1)](递减)。
  • 如果 i 是奇数,则 values[p_i] < values[p_(i+1)](递增)。

换句话说,路径上节点值的比较符号是交替的(<, >, <, >, ... 或 >, <, >, <, ...)。路径的长度定义为路径上边的数量(即节点数减1)。单节点路径长度为0,也视为交错路径。

你的任务是:找到图中最长交错路径的长度。注意路径不一定是简单路径,可以有环吗?通常我们要求路径是简单路径(无重复节点),但本题目通常限定为简单路径(无环)。我们假设图是有向无环图(DAG),这样我们可以用动态规划按拓扑顺序求解。如果图中可能有环,则问题会变得更复杂(需要处理环)。为了简化,我们先考虑有向无环图(DAG)的情况。

输入

  • 整数 n,表示节点数。
  • 数组 values,长度为 n,values[i] 表示节点 i 的值。
  • 整数 m,表示边数。
  • 接下来 m 行,每行两个整数 u, v,表示一条从 u 到 v 的有向边。保证图中无环(DAG)。

输出:一个整数,表示最长交错路径的长度。

示例

n = 4
values = [1, 2, 3, 4]
边:0->1, 1->2, 2->3

解释:所有节点值严格递增。如果路径必须以交替方式,那么最长交错路径是单个节点(长度为0)。比如路径 0->1 是递增的,但接下来如果走 1->2 又是递增,不满足交替(我们需要递增后紧跟递减,或者递减后紧跟递增)。所以最长路径可能是 0->1(长度1,但这是单一的递增,不符合交替?实际上,单条边路径(长度为1)总是满足交替吗?对于长度为1的路径,它只有一个比较,可以是任意比较,所以总是满足交替条件。所以长度为1的路径是合法的。但我们需要更长的路径。在此例中,由于所有值递增,任何长度为2的路径(两条边)都无法同时满足递增和递减交替。例如 0->1->2:0->1 是递增,1->2 也是递增,第二个比较不是递减,所以不合法。所以最长交错路径长度为1。

另一个例子:

n = 5
values = [5, 3, 4, 2, 1]
边:0->1, 1->2, 2->3, 3->4, 0->2, 1->3, 2->4]

一个可能的最长交错路径:0->1 (5>3 递减), 1->2 (3<4 递增), 2->3 (4>2 递减), 3->4 (2>1 递减) 但这里 2->3 递减,3->4 也递减,不交替。实际上,如果我们取 0->1 (递减), 1->2 (递增), 2->3 (递减) 长度3,是合法的。所以答案是3。

解题目标:在DAG中,找到满足值交替大小关系的最长路径长度。

解题思路

这是一个基于图的动态规划问题。由于图是无环的,我们可以按照拓扑顺序处理节点。对于每个节点,我们需要考虑以该节点为终点的最长交错路径。但由于交替规则,我们需要知道当前路径的最后一步是比较方向(是递增还是递减),才能决定下一步可以接什么样的边。

状态定义
定义两个状态数组:

  • inc[i]:表示以节点 i 为路径最后一个节点,且最后一步比较是递增(即从某个节点 j 到 i 满足 values[j] < values[i])的情况下,从某个起点到 i 的最长交错路径长度。
  • dec[i]:表示以节点 i 为路径最后一个节点,且最后一步比较是递减(即从某个节点 j 到 i 满足 values[j] > values[i])的情况下,从某个起点到 i 的最长交错路径长度。

注意:这里“最后一步比较”指的是到达 i 的那条边上的比较。对于 inc[i],意味着到达 i 之前的那一步是递增(即前驱节点的值小于 i 的值)。对于 dec[i],意味着到达 i 之前的那一步是递减(前驱节点的值大于 i 的值)。

转移方程
我们考虑所有指向节点 i 的入边 (j, i)。根据边上的值比较关系,更新 inc[i] 和 dec[i]。

  • 如果 values[j] < values[i](递增边):
    那么从 j 到 i 是递增。如果我们想要以 i 结尾且最后一步是递增的路径,那么这条路径的前一步(以 j 结尾)的最后一步应该是递减(因为我们需要交替:递减后接递增)。所以我们可以用 dec[j] 来更新 inc[i]。
    转移:inc[i] = max(inc[i], dec[j] + 1)
  • 如果 values[j] > values[i](递减边):
    那么从 j 到 i 是递减。类似地,如果我们想要以 i 结尾且最后一步是递减的路径,那么前一步应该是以 j 结尾且最后一步是递增的路径。所以用 inc[j] 来更新 dec[i]。
    转移:dec[i] = max(dec[i], inc[j] + 1)

初始化:对于每个节点 i,inc[i] = 0, dec[i] = 0。因为单个节点路径长度为0,且没有最后一步比较方向,但我们可以认为 inc 和 dec 都至少为0。实际上,单个节点路径没有边,所以没有比较方向。但为了方便,我们初始化 inc 和 dec 为0,表示从该节点开始(或结束)的路径长度为0。当我们处理边时,会加上1。

计算顺序
由于图是DAG,我们可以先进行拓扑排序,然后按照拓扑顺序依次处理每个节点 i。对于每个节点 i,我们遍历其所有入边(即所有前驱 j),根据上述规则更新 inc[i] 和 dec[i]。因为拓扑排序保证处理 i 时,其所有前驱 j 已经被处理过了(即 inc[j] 和 dec[j] 已经计算好了)。

最终答案
遍历所有节点 i,取 max(inc[i], dec[i]) 的最大值,即为最长交错路径的长度。

注意:路径长度是边的数量。我们初始化 inc 和 dec 为0,表示路径长度为0(单个节点)。当从 j 扩展到 i 时,路径长度增加1(即边 j->i)。所以转移方程中 +1 是正确的。

边界情况

  • 如果图中没有边,则每个节点都是孤立点,最长路径长度为0。
  • 如果所有边都满足同一种比较(全递增或全递减),则最长交错路径长度为1(因为只有一条边的路径总是合法,两条边就需要交替,而全同向无法交替,所以长度最多为1)。

复杂度

  • 拓扑排序 O(n + m)。
  • 动态规划过程:对于每条边,我们进行常数次更新。总时间复杂度 O(n + m)。空间复杂度 O(n)。

逐步推导

我们用一个具体例子来演示。

假设:
n = 6
values = [5, 2, 4, 3, 1, 6]
边:
0->1 (5>2 递减)
0->2 (5>4 递减)
1->3 (2<3 递增)
2->3 (4>3 递减)
2->4 (4>1 递减)
3->5 (3<6 递增)
4->5 (1<6 递增)

图结构如下(箭头表示有向边,旁边标注比较关系):

节点0 (5)
  ↘ 递减
   节点1 (2) → 递增 → 节点3 (3) → 递增 → 节点5 (6)
  ↘ 递减                     ↗
   节点2 (4) → 递减 → 节点4 (1) → 递增 → 节点5
        ↘ 递减 ↘
          节点3  节点4

注意:0->2 递减,2->3 递减,2->4 递减,等等。

我们需要计算最长交错路径。

步骤1:拓扑排序
这个图是DAG,一种拓扑顺序可以是 [0,1,2,3,4,5](实际上可能有多种,但0入度为0,之后1和2入度来自0,3入度来自1和2,4入度来自2,5入度来自3和4)。我们按此顺序处理。

初始化:
inc = [0,0,0,0,0,0]
dec = [0,0,0,0,0,0]

步骤2:按拓扑顺序处理每个节点

  • 节点0:没有入边,所以 inc[0] 和 dec[0] 保持0。

  • 节点1:入边 0->1 (5>2 递减)。
    比较:values[0]=5 > values[1]=2,是递减边。
    因此,我们可以用 inc[0] 来更新 dec[1]。
    dec[1] = max(dec[1], inc[0]+1) = max(0, 0+1) = 1。
    inc[1] 保持不变(因为没有递增入边)。
    现在 inc[1]=0, dec[1]=1。

  • 节点2:入边 0->2 (5>4 递减)。
    递减边,用 inc[0] 更新 dec[2]。
    dec[2] = max(0, inc[0]+1) = 1。
    inc[2]=0。

  • 节点3:有两条入边:

    1. 边 1->3: values[1]=2 < values[3]=3,递增边。
      对于递增边,我们用 dec[1] 更新 inc[3]。
      inc[3] = max(inc[3], dec[1]+1) = max(0, 1+1) = 2。
    2. 边 2->3: values[2]=4 > values[3]=3,递减边。
      对于递减边,我们用 inc[2] 更新 dec[3]。
      dec[3] = max(dec[3], inc[2]+1) = max(0, 0+1) = 1。
      所以 inc[3]=2, dec[3]=1。
  • 节点4:入边 2->4: values[2]=4 > values[4]=1,递减边。
    用 inc[2] 更新 dec[4]。
    dec[4] = max(0, inc[2]+1) = 1。
    inc[4]=0。

  • 节点5:有两条入边:

    1. 边 3->5: values[3]=3 < values[5]=6,递增边。
      用 dec[3] 更新 inc[5]。
      inc[5] = max(inc[5], dec[3]+1) = max(0, 1+1) = 2。
    2. 边 4->5: values[4]=1 < values[5]=6,递增边。
      用 dec[4] 更新 inc[5]。
      inc[5] = max(inc[5], dec[4]+1) = max(2, 1+1) = 2。(相等,还是2)
      没有递减入边,所以 dec[5]=0。

步骤3:计算答案
对于每个节点,取 inc 和 dec 的最大值:
节点0: max(0,0)=0
节点1: max(0,1)=1
节点2: max(0,1)=1
节点3: max(2,1)=2
节点4: max(0,1)=1
节点5: max(2,0)=2
所以最大值是2,即最长交错路径长度为2。

验证:我们可以找到长度为2的路径,例如 0->1 (递减), 1->3 (递增) 长度2。还有 0->2 (递减), 2->3 (递减) 不交替,不行。还有 2->3 (递减), 3->5 (递增) 长度2。所以答案为2。

思考:如果路径可以更长,比如 0->1 (递减), 1->3 (递增), 3->5 (递增) 最后两步都是递增,不交替。所以最长就是2。

扩展讨论

如果图中有环怎么办?此时无法进行拓扑排序,因为存在循环依赖。但交错路径要求简单路径(无重复节点),所以不能包含环。我们可以考虑在一般有向图中找最长简单路径,但这是NP难的(因为最长路径问题是NP难的)。所以通常题目会限定为DAG,或者要求路径是简单的但图是任意有向图,此时可能需要用记忆化搜索+状态压缩(节点数少时)或使用DFS+记忆化。

对于有向图(可能有环),但要求简单路径,我们可以用记忆化搜索,状态为 (当前节点, 上一步比较方向),用DFS遍历所有简单路径,但最坏情况是指数复杂度。如果节点数n较小(比如n≤20),可以用状态压缩DP。

代码实现(伪代码)

function longestAlternatingPath(n, values, edges):
    # 建图,邻接表存储出边,同时为了方便,我们也存储入边或直接遍历边列表
    # 由于需要按照拓扑顺序,我们先计算每个节点的入度,进行拓扑排序
    indeg = [0]*n
    adj = [[] for _ in range(n)]  # 出边列表
    for (u,v) in edges:
        adj[u].append(v)
        indeg[v] += 1
    
    # 拓扑排序
    from collections import deque
    q = deque()
    for i in range(n):
        if indeg[i] == 0:
            q.append(i)
    topo = []
    while q:
        u = q.popleft()
        topo.append(u)
        for v in adj[u]:
            indeg[v] -= 1
            if indeg[v] == 0:
                q.append(v)
    # 如果图中存在环,拓扑排序后 topo 长度小于 n,但题目保证无环,所以略过处理

    inc = [0]*n
    dec = [0]*n
    ans = 0
    # 按照拓扑顺序处理节点
    for u in topo:
        # 遍历所有入边,我们需要存储入边列表,或者直接遍历所有边
        # 为了效率,可以预先存储入边列表
        # 这里为了简单,我们遍历所有边,检查终点是否为 u
        # 实际实现时可以建立反向邻接表
    # 更高效的做法:在构建图时同时构建反向邻接表 rev_adj
    rev_adj = [[] for _ in range(n)]
    for (u,v) in edges:
        rev_adj[v].append(u)  # 存储进入 v 的边
    
    for u in topo:
        for prev in rev_adj[u]:
            if values[prev] < values[u]:  # 递增边
                inc[u] = max(inc[u], dec[prev] + 1)
            elif values[prev] > values[u]:  # 递减边
                dec[u] = max(dec[u], inc[prev] + 1)
        ans = max(ans, inc[u], dec[u])
    return ans

总结:本题的核心是将路径的交替性质用两个状态表示,然后利用DAG的拓扑顺序进行动态规划。状态转移依赖于前驱节点和值的大小关系。最终取所有状态的最大值作为答案。

最长交错路径(Longest Alternating Path in a Directed Graph) 题目描述 给你一个有向图,图中有 n 个节点,节点编号从 0 到 n-1。同时给你一个整数数组 values ,其中 values[i] 表示节点 i 的值。图中还有 m 条有向边,每条边从节点 u 指向节点 v。 我们定义一个路径为“交错路径”,如果路径上相邻节点的值交替严格递增和严格递减。更形式化地,对于一个节点序列 p0, p1, ..., pk ,对于所有满足 0 ≤ i < k 的 i,必须满足以下条件之一: 如果 i 是偶数,则 values[p_i] < values[p_(i+1)] (递增)。 如果 i 是奇数,则 values[p_i] > values[p_(i+1)] (递减)。 或者反过来: 如果 i 是偶数,则 values[p_i] > values[p_(i+1)] (递减)。 如果 i 是奇数,则 values[p_i] < values[p_(i+1)] (递增)。 换句话说,路径上节点值的比较符号是交替的( < , > , < , > , ... 或 > , < , > , < , ...)。路径的长度定义为路径上边的数量(即节点数减1)。单节点路径长度为0,也视为交错路径。 你的任务是:找到图中最长交错路径的长度。注意路径不一定是简单路径,可以有环吗?通常我们要求路径是简单路径(无重复节点),但本题目通常限定为简单路径(无环)。我们假设图是有向无环图(DAG),这样我们可以用动态规划按拓扑顺序求解。如果图中可能有环,则问题会变得更复杂(需要处理环)。为了简化,我们先考虑有向无环图(DAG)的情况。 输入 : 整数 n,表示节点数。 数组 values,长度为 n,values[ i ] 表示节点 i 的值。 整数 m,表示边数。 接下来 m 行,每行两个整数 u, v,表示一条从 u 到 v 的有向边。保证图中无环(DAG)。 输出 :一个整数,表示最长交错路径的长度。 示例 : 解释:所有节点值严格递增。如果路径必须以交替方式,那么最长交错路径是单个节点(长度为0)。比如路径 0->1 是递增的,但接下来如果走 1->2 又是递增,不满足交替(我们需要递增后紧跟递减,或者递减后紧跟递增)。所以最长路径可能是 0->1(长度1,但这是单一的递增,不符合交替?实际上,单条边路径(长度为1)总是满足交替吗?对于长度为1的路径,它只有一个比较,可以是任意比较,所以总是满足交替条件。所以长度为1的路径是合法的。但我们需要更长的路径。在此例中,由于所有值递增,任何长度为2的路径(两条边)都无法同时满足递增和递减交替。例如 0->1->2:0->1 是递增,1->2 也是递增,第二个比较不是递减,所以不合法。所以最长交错路径长度为1。 另一个例子: 一个可能的最长交错路径:0->1 (5>3 递减), 1->2 (3 <4 递增), 2->3 (4>2 递减), 3->4 (2>1 递减) 但这里 2->3 递减,3->4 也递减,不交替。实际上,如果我们取 0->1 (递减), 1->2 (递增), 2->3 (递减) 长度3,是合法的。所以答案是3。 解题目标 :在DAG中,找到满足值交替大小关系的最长路径长度。 解题思路 这是一个基于图的动态规划问题。由于图是无环的,我们可以按照拓扑顺序处理节点。对于每个节点,我们需要考虑以该节点为终点的最长交错路径。但由于交替规则,我们需要知道当前路径的最后一步是比较方向(是递增还是递减),才能决定下一步可以接什么样的边。 状态定义 : 定义两个状态数组: inc[i] :表示以节点 i 为路径最后一个节点,且最后一步比较是 递增 (即从某个节点 j 到 i 满足 values[ j] < values[ i ])的情况下,从某个起点到 i 的最长交错路径长度。 dec[i] :表示以节点 i 为路径最后一个节点,且最后一步比较是 递减 (即从某个节点 j 到 i 满足 values[ j] > values[ i ])的情况下,从某个起点到 i 的最长交错路径长度。 注意:这里“最后一步比较”指的是到达 i 的那条边上的比较。对于 inc[ i],意味着到达 i 之前的那一步是递增(即前驱节点的值小于 i 的值)。对于 dec[ i ],意味着到达 i 之前的那一步是递减(前驱节点的值大于 i 的值)。 转移方程 : 我们考虑所有指向节点 i 的入边 (j, i)。根据边上的值比较关系,更新 inc[ i] 和 dec[ i ]。 如果 values[ j] < values[ i ](递增边): 那么从 j 到 i 是递增。如果我们想要以 i 结尾且最后一步是递增的路径,那么这条路径的前一步(以 j 结尾)的最后一步应该是递减(因为我们需要交替:递减后接递增)。所以我们可以用 dec[ j] 来更新 inc[ i ]。 转移: inc[i] = max(inc[i], dec[j] + 1) 。 如果 values[ j] > values[ i ](递减边): 那么从 j 到 i 是递减。类似地,如果我们想要以 i 结尾且最后一步是递减的路径,那么前一步应该是以 j 结尾且最后一步是递增的路径。所以用 inc[ j] 来更新 dec[ i ]。 转移: dec[i] = max(dec[i], inc[j] + 1) 。 初始化:对于每个节点 i, inc[i] = 0 , dec[i] = 0 。因为单个节点路径长度为0,且没有最后一步比较方向,但我们可以认为 inc 和 dec 都至少为0。实际上,单个节点路径没有边,所以没有比较方向。但为了方便,我们初始化 inc 和 dec 为0,表示从该节点开始(或结束)的路径长度为0。当我们处理边时,会加上1。 计算顺序 : 由于图是DAG,我们可以先进行拓扑排序,然后按照拓扑顺序依次处理每个节点 i。对于每个节点 i,我们遍历其所有入边(即所有前驱 j),根据上述规则更新 inc[ i] 和 dec[ i]。因为拓扑排序保证处理 i 时,其所有前驱 j 已经被处理过了(即 inc[ j] 和 dec[ j ] 已经计算好了)。 最终答案 : 遍历所有节点 i,取 max(inc[i], dec[i]) 的最大值,即为最长交错路径的长度。 注意 :路径长度是边的数量。我们初始化 inc 和 dec 为0,表示路径长度为0(单个节点)。当从 j 扩展到 i 时,路径长度增加1(即边 j->i)。所以转移方程中 +1 是正确的。 边界情况 : 如果图中没有边,则每个节点都是孤立点,最长路径长度为0。 如果所有边都满足同一种比较(全递增或全递减),则最长交错路径长度为1(因为只有一条边的路径总是合法,两条边就需要交替,而全同向无法交替,所以长度最多为1)。 复杂度 : 拓扑排序 O(n + m)。 动态规划过程:对于每条边,我们进行常数次更新。总时间复杂度 O(n + m)。空间复杂度 O(n)。 逐步推导 我们用一个具体例子来演示。 假设: n = 6 values = [ 5, 2, 4, 3, 1, 6 ] 边: 0->1 (5>2 递减) 0->2 (5>4 递减) 1->3 (2 <3 递增) 2->3 (4>3 递减) 2->4 (4>1 递减) 3->5 (3 <6 递增) 4->5 (1 <6 递增) 图结构如下(箭头表示有向边,旁边标注比较关系): 注意:0->2 递减,2->3 递减,2->4 递减,等等。 我们需要计算最长交错路径。 步骤1:拓扑排序 这个图是DAG,一种拓扑顺序可以是 [ 0,1,2,3,4,5 ](实际上可能有多种,但0入度为0,之后1和2入度来自0,3入度来自1和2,4入度来自2,5入度来自3和4)。我们按此顺序处理。 初始化: inc = [ 0,0,0,0,0,0 ] dec = [ 0,0,0,0,0,0 ] 步骤2:按拓扑顺序处理每个节点 节点0:没有入边,所以 inc[ 0] 和 dec[ 0 ] 保持0。 节点1:入边 0->1 (5>2 递减)。 比较:values[ 0]=5 > values[ 1 ]=2,是递减边。 因此,我们可以用 inc[ 0] 来更新 dec[ 1 ]。 dec[ 1] = max(dec[ 1], inc[ 0 ]+1) = max(0, 0+1) = 1。 inc[ 1 ] 保持不变(因为没有递增入边)。 现在 inc[ 1]=0, dec[ 1 ]=1。 节点2:入边 0->2 (5>4 递减)。 递减边,用 inc[ 0] 更新 dec[ 2 ]。 dec[ 2] = max(0, inc[ 0 ]+1) = 1。 inc[ 2 ]=0。 节点3:有两条入边: 边 1->3: values[ 1]=2 < values[ 3 ]=3,递增边。 对于递增边,我们用 dec[ 1] 更新 inc[ 3 ]。 inc[ 3] = max(inc[ 3], dec[ 1 ]+1) = max(0, 1+1) = 2。 边 2->3: values[ 2]=4 > values[ 3 ]=3,递减边。 对于递减边,我们用 inc[ 2] 更新 dec[ 3 ]。 dec[ 3] = max(dec[ 3], inc[ 2 ]+1) = max(0, 0+1) = 1。 所以 inc[ 3]=2, dec[ 3 ]=1。 节点4:入边 2->4: values[ 2]=4 > values[ 4 ]=1,递减边。 用 inc[ 2] 更新 dec[ 4 ]。 dec[ 4] = max(0, inc[ 2 ]+1) = 1。 inc[ 4 ]=0。 节点5:有两条入边: 边 3->5: values[ 3]=3 < values[ 5 ]=6,递增边。 用 dec[ 3] 更新 inc[ 5 ]。 inc[ 5] = max(inc[ 5], dec[ 3 ]+1) = max(0, 1+1) = 2。 边 4->5: values[ 4]=1 < values[ 5 ]=6,递增边。 用 dec[ 4] 更新 inc[ 5 ]。 inc[ 5] = max(inc[ 5], dec[ 4 ]+1) = max(2, 1+1) = 2。(相等,还是2) 没有递减入边,所以 dec[ 5 ]=0。 步骤3:计算答案 对于每个节点,取 inc 和 dec 的最大值: 节点0: max(0,0)=0 节点1: max(0,1)=1 节点2: max(0,1)=1 节点3: max(2,1)=2 节点4: max(0,1)=1 节点5: max(2,0)=2 所以最大值是2,即最长交错路径长度为2。 验证:我们可以找到长度为2的路径,例如 0->1 (递减), 1->3 (递增) 长度2。还有 0->2 (递减), 2->3 (递减) 不交替,不行。还有 2->3 (递减), 3->5 (递增) 长度2。所以答案为2。 思考 :如果路径可以更长,比如 0->1 (递减), 1->3 (递增), 3->5 (递增) 最后两步都是递增,不交替。所以最长就是2。 扩展讨论 如果图中有环怎么办?此时无法进行拓扑排序,因为存在循环依赖。但交错路径要求简单路径(无重复节点),所以不能包含环。我们可以考虑在一般有向图中找最长简单路径,但这是NP难的(因为最长路径问题是NP难的)。所以通常题目会限定为DAG,或者要求路径是简单的但图是任意有向图,此时可能需要用记忆化搜索+状态压缩(节点数少时)或使用DFS+记忆化。 对于有向图(可能有环),但要求简单路径,我们可以用记忆化搜索,状态为 (当前节点, 上一步比较方向),用DFS遍历所有简单路径,但最坏情况是指数复杂度。如果节点数n较小(比如n≤20),可以用状态压缩DP。 代码实现(伪代码) 总结 :本题的核心是将路径的交替性质用两个状态表示,然后利用DAG的拓扑顺序进行动态规划。状态转移依赖于前驱节点和值的大小关系。最终取所有状态的最大值作为答案。