1 条题解

  • 0
    @ 2026-10-26 22:50:07

    思路与算法

    反向BFS先求原图可达终点的点,再一次性排除有出边指向不可达点的顶点;在剩余点诱导图正向BFS求最短路。

    正确性说明

    题目条件中的可达指原图可达终点,反向遍历恰求此集合。某点所有出边目标在该集合当且仅当该点可出现在答案路径上。删掉不合格点后,余图任一路径满足条件,BFS因边权1求最短。

    复杂度

    O(n+m)时间、O(n+m)空间,含正反邻接表与两次遍历初始化。

    易错点

    不要在删点后反复传播失效,可达集合只按原图计算;重边、自环都可能存在,终点没有出边。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n, m;
        cin >> n >> m;
        vector<vector<int>> g(n), rev(n);
        while (m--) {
            int a, b;
            cin >> a >> b;
            --a;
            --b;
            g[a].push_back(b);
            rev[b].push_back(a);
        }
        int s, t;
        cin >> s >> t;
        --s;
        --t;
        vector<int> reach(n), good(n, 1), q(1, t);
        reach[t] = 1;
        for (int i = 0; i < (int)q.size(); i++)
            for (int v : rev[q[i]])
                if (!reach[v]) {
                    reach[v] = 1;
                    q.push_back(v);
                }
        for (int i = 0; i < n; i++) {
            good[i] = reach[i];
            for (int v : g[i])
                if (!reach[v])
                    good[i] = 0;
        }
        if (!good[s]) {
            cout << -1 << "\n";
            return 0;
        }
        vector<int> d(n, -1);
        d[s] = 0;
        q.assign(1, s);
        for (int i = 0; i < (int)q.size(); i++)
            for (int v : g[q[i]])
                if (good[v] && d[v] < 0) {
                    d[v] = d[q[i]] + 1;
                    q.push_back(v);
                }
        cout << d[t] << "\n";
    }
    
    • 1

    信息

    ID
    1915
    时间
    1000ms
    内存
    128MiB
    难度
    普及−
    标签
    递交数
    0
    已通过
    0
    上传者