1 条题解

  • 0
    @ 2026-4-2 14:49:28

    题目题解

    问题理解

    给定一个简单无向连通图,从顶点 11 出发,每个顶点 uu 的边按输入顺序编号为 11deg(u)\deg(u)。在时间 tt,若位于顶点 uu,必须执行以下操作之一:

    • 等待一秒,
    • 通过顶点 uu 的第 (tmoddeg(u)+1)(t \bmod \deg(u) + 1) 条边移动到邻接点,耗时一秒。

    求从顶点 11 到顶点 nn 的最短总时间,以及在此最短总时间下的最少等待时间。


    状态定义

    f(i,j)f(i, j) 表示在时间 jj 到达顶点 ii 所需的最少等待时间。初始状态为

    f(1,0)=0.f(1, 0) = 0.

    状态转移

    在时间 jj 位于顶点 ii,有以下两种转移:

    1. 等待一秒
      时间变为 j+1j+1,等待时间增加 11

      $$f(i, j+1) \leftarrow \min\big(f(i, j+1),\; f(i, j) + 1\big). $$
    2. 移动
      kk 为顶点 ii 的第 (jmoddeg(i)+1)(j \bmod \deg(i) + 1) 条边所连的顶点。则移动后时间变为 j+1j+1,等待时间不变:

      $$f(k, j+1) \leftarrow \min\big(f(k, j+1),\; f(i, j)\big). $$

    目标

    xx 为从 11nn 的最短总时间,则最小等待时间为

    f(n,x).f(n, x).

    因此,只需对所有 jxj \le x 计算 f(i,j)f(i, j)


    时间复杂度分析

    若直接计算到时间 xx,复杂度为 O(nx+m)O(n x + m)
    我们需要给出 xx 的上界。


    上界 x3nx \le 3n

    引理:存在一条从 11nn 的路径,其顶点度数之和 d3nd \le 3n

    证明

    • 取一条从 11nn 的最短路径(边数最少),设路径上有 kk 个顶点。
    • 由于路径是最短的,不存在连接路径上非相邻顶点的边(否则可缩短路径)。
    • 也不存在路径外的一个顶点与路径上至少 44 个顶点相邻,因为那样同样可以缩短路径。

    因此,路径上每个顶点的度数最多为 22(与路径上前后顶点相邻)加上可能的路径外邻接点。
    由于每个路径外顶点最多与 33 个路径上顶点相邻,所以路径上顶点的度数之和满足:

    $$\sum_{u \in \text{path}} \deg(u) \le 2k + 3(n - k) = 3n - k. $$

    由于 k2k \ge 2,有

    upathdeg(u)3n.\sum_{u \in \text{path}} \deg(u) \le 3n.

    最坏情况下的总时间

    考虑这条路径,最坏策略是每次前进前等待到该顶点对应边出现。
    对于路径上的顶点 uu,最多等待 deg(u)1\deg(u) - 1 次(因为总有一时刻当前边就是要用的边)。
    因此,总时间不超过路径上所有顶点的度数之和,即 x3nx \le 3n


    算法复杂度

    由于 x3nx \le 3n,我们可以计算所有 j3nj \le 3n 的状态。
    状态数 O(n3n)=O(n2)O(n \cdot 3n) = O(n^2),每个状态转移 O(1)O(1),加上边信息预处理 O(m)O(m),总复杂度为

    O(n2+m).O(n^2 + m).

    对于 n5000n \le 5000n5000\sum n \le 5000,这是可行的。


    算法步骤

    1. 读入图,计算每个顶点的度数及边的顺序。
    2. 初始化 f(1,0)=0f(1,0) = 0,其余 f(i,j)=f(i,j) = \infty
    3. j=0j = 03n13n-1
      • 对于每个顶点 ii,若 f(i,j)f(i,j) 已知:
        • 更新 f(i,j+1)=min(f(i,j+1),f(i,j)+1)f(i, j+1) = \min(f(i, j+1), f(i,j) + 1)
        • kkii 的第 (jmoddeg(i)+1)(j \bmod \deg(i) + 1) 条边的另一端点,更新 f(k,j+1)=min(f(k,j+1),f(i,j))f(k, j+1) = \min(f(k, j+1), f(i,j))
    4. 找到最小的 xx 使得 f(n,x)f(n, x) 有限,输出 xxf(n,x)f(n, x)

    代码实现

    #include <bits/stdc++.h>
    using namespace std;
    
    const int INF = 1e9;
    
    void solve() {
        int n, m;
        cin >> n >> m;
        
        vector<vector<int>> g(n);
        vector<int> deg(n, 0);
        
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            u--; v--;
            g[u].push_back(v);
            g[v].push_back(u);
            deg[u]++;
            deg[v]++;
        }
        
        int max_time = 3 * n;  // 上界
        
        // f[i][j] = 在时间 j 到达顶点 i 的最少等待时间
        vector<vector<int>> f(n, vector<int>(max_time + 1, INF));
        f[0][0] = 0;
        
        for (int j = 0; j < max_time; j++) {
            for (int i = 0; i < n; i++) {
                if (f[i][j] == INF) continue;
                
                // 等待操作
                f[i][j + 1] = min(f[i][j + 1], f[i][j] + 1);
                
                // 移动操作
                int edge_idx = j % deg[i];
                int to = g[i][edge_idx];
                f[to][j + 1] = min(f[to][j + 1], f[i][j]);
            }
        }
        
        // 寻找答案
        int best_time = INF, best_wait = INF;
        for (int j = 0; j <= max_time; j++) {
            if (f[n - 1][j] < best_time) {
                best_time = j;
                best_wait = f[n - 1][j];
            } else if (f[n - 1][j] == best_time) {
                best_wait = min(best_wait, f[n - 1][j]);
            }
        }
        
        cout << best_time << " " << best_wait << "\n";
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
        
        return 0;
    }
    

    验证样例

    样例 1:输出 4 2
    样例 2:输出 3 0


    总结

    本题的关键在于:

    1. 将问题转化为带时间维度的状态搜索。
    2. 利用最短路径的性质给出时间上界 3n3n,从而将复杂度控制在 O(n2+m)O(n^2 + m)
    3. 通过动态规划或 BFS 在有限时间范围内求解,并同时记录最少等待时间。
    • 1

    信息

    ID
    6224
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    递交数
    1
    已通过
    1
    上传者