leetcode 5699(dijkstra)

leetcode 5699 从第一个节点出发到最后一个节点的受限路径数

所谓从节点 \(1\) 到节点 \(n\) 的受限路径,就是从 \(1\) 号节点出发,每一步必须到达离 \(n\) 号节点更近的节点。

\(dp_i\) 为从节点 \(i\) 到节点 \(n\) 的受限路径数,显然 \(dp_n=1\)

可以先求出以 \(n\) 号节点为源点的单源最短路,然后从节点 \(n\) 开始,由近及远 \(dp\)

typedef long long LL;
struct E {int v, w;};
struct node {
    int u; LL w;
    bool operator<(const node &t) const {
        return w > t.w;
    }
};
const int mod = 1e9+7;
class Solution {
public:
    int countRestrictedPaths(int n, vector<vector<int>>& edges) {
        vector<vector<E>> G(n+1);
        for (auto &edge : edges) {
            G[edge[0]].push_back(E{edge[1], edge[2]});
            G[edge[1]].push_back(E{edge[0], edge[2]});
        }
        
        // dijkstra
        vector<LL> dis(n+1, LLONG_MAX/10);
        priority_queue<node> Q;
        dis[n] = 0;
        Q.push(node{n, 0});
        while (!Q.empty()) {
            node t = Q.top(); Q.pop();
            if (dis[t.u] != t.w) continue;
            //cout << t.u << '#' << t.w << endl;
            for (auto &g : G[t.u]) {
                //cout << '!' << t.w << '-' << g.w << '-' << dis[g.v] << endl;
                if (t.w+g.w < dis[g.v]) {
                    dis[g.v] = t.w+g.w;
                    Q.push(node{g.v, dis[g.v]});
                }
            }
        }
        
        // dp
        vector<LL> dp(n+1); dp[n] = 1;
        vector<int> q(n+1);
        iota(q.begin(), q.end(), 0);
        sort(q.begin()+1, q.end(), [&](int a, int b) {
            return dis[a] < dis[b];
        });
        
        vector<int> vis(n+1);
        for (int u : q) {
            //cout << "==" << u << endl;
            for (auto &g : G[u]) {
                //cout << '!' << g.v << ' ' << dis[g.v] << ' ' << g.w << ' ' << dis[u] << endl;
                if (!vis[g.v]) continue;
                if (dis[g.v] < dis[u]) {
                    dp[u] += dp[g.v];
                    dp[u] %= mod;
                    //cout << "!!" << u << ' ' << dp[u] << endl;
                }
            }
            vis[u] = 1;
        }
        return dp[1];
    }
};

看了大佬的题解,发现原来完全可以在 \(dijkstra\) 过程中进行 \(dp\) 转移,学到了学到了。

typedef long long LL;
struct E {int v, w;};
struct node {
    int u; LL w;
    bool operator<(const node &t) const {
        return w > t.w;
    }
};
const int mod = 1e9+7;
class Solution {
public:
    int countRestrictedPaths(int n, vector<vector<int>>& edges) {
        vector<vector<E>> G(n+1);
        for (auto &edge : edges) {
            G[edge[0]].push_back(E{edge[1], edge[2]});
            G[edge[1]].push_back(E{edge[0], edge[2]});
        }
        vector<LL> dis(n+1, LLONG_MAX/10);
        vector<LL> dp(n+1);
        priority_queue<node> Q;
        dis[n] = 0; dp[n] = 1;
        Q.push(node{n, 0});
        while (!Q.empty()) {
            node t = Q.top(); Q.pop();
            if (dis[t.u] != t.w) continue;
            //cout << t.u << '#' << t.w << endl;
            for (auto &g : G[t.u]) {
                //cout << '!' << t.w << '-' << g.w << '-' << dis[g.v] << endl;
                if (t.w+g.w < dis[g.v]) {
                    dis[g.v] = t.w+g.w;
                    Q.push(node{g.v, dis[g.v]});
                }

                if (dis[g.v] < dis[t.u]) {
                    dp[t.u] += dp[g.v];
                    dp[t.u] %= mod;
                }
            }
        }

        return dp[1];
    }
};
posted @ 2021-03-07 13:15  Zewbie  阅读(86)  评论(0)    收藏  举报