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];
}
};