leetcode--1976. 到达目的地的方案数(最短路)
记录
12:05 2024-3-5
https://leetcode.cn/problems/number-of-ways-to-arrive-at-destination/
通过最短路找到从源点到目标点距离,在更新的过程中,对某个点记录下可以达到最短距离的父亲节点,然后从目标点往回dp就可以了(有种逆向拓扑排序的感觉)
当然这是不必要的,在更新最短距离的时候就可以用dp去查找达到最短距离的方案数了
1.记录下达到最短路时候到该点的边(多此一举)
点击查看代码
#include "bits/stdc++.h"
#define rep(i, a, n) for (auto i = a; i < (n); ++i) // repeat
#define repe(i, a, n) for (auto i = a; i <= (n); ++i) // repeat and equal
#define revrep(i, a, n) for (auto i = n; i > (a); --i) // reverse repeat
#define revrepe(i, a, n) for (auto i = n; i >= (a); --i)
#define all(a) a.begin(), a.end()
#define sz(a) (int)(a.size());
#define mem(a,b) memset(a,b,sizeof(a))
#define lb(x) ((x) & -(x)) // lowbit
#define pb push_back
#define qb pop_back
#define pf push_front
#define qf pop_front
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
template<class T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
template<typename T>
ostream & operator << (ostream &out,const set<T>&obj){out<<"set(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<typename T>
ostream & operator << (ostream &out,const unordered_set<T>&obj){out<<"unordered_set(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const map<T1,T2>&obj){out<<"map(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<it->first<<": "<<it->second;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const unordered_map<T1,T2>&obj){out<<"unordered_map(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<it->first<<": "<<it->second;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const pair<T1,T2>&obj){out<<"<"<<obj.first<<", "<<obj.second<<">";return out;}
template<typename T>
ostream & operator << (ostream &out,const vector<T>&obj){out<<"vector(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<class A, class B> string to_string(const pair<A, B> &p);
template<class A, class B, class C> string to_string(const tuple<A, B, C> &p);
template<class A, class B, class C, class D> string to_string(const tuple<A, B, C, D> &p);
string to_string(const string &s) { return '"' + s + '"'; }
string to_string(const char *s) { return to_string((string) s); }
string to_string(char c) { return "'" + string(1, c) + "'"; }
string to_string(bool x) { return x ? "true" : "false"; }
template<size_t L> string to_string(const bitset<L> &x) { return x.to_string(); }
template<class A, class T = typename A::value_type> string to_string(const A &v) {
bool first = 1;
string res = "{";
for (const auto &x: v) {
if (!first) res += ", ";
first = 0;
res += to_string(x);
}
res += "}";
return res;
}
template<class A, class B> string to_string(const pair<A, B> &p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template<class A, class B, class C> string to_string(const tuple<A, B, C> &p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
template<class A, class B, class C, class D> string to_string(const tuple<A, B, C, D> &p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
class Solution {
public:
int countPaths(int n, vector<vector<int>>& roads) {
// dijkstra求俩点之间最短距离
ll mod = 1e9 + 7;
vector<ll> d(n, LLONG_MAX);
vector vis(n, 0);
// 记录图
vector<vector<pii>> g(n, vector<pii>{});
for(const auto &road : roads) {
g[road[0]].push_back({road[1], road[2]});
g[road[1]].push_back({road[0], road[2]});
}
// 记录到某个点可以达到最短距离的边
vector<vector<pii>> edges(n, vector<pii>{});
auto dijkstra = [&] (int s) {
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>> > pq;
d[s] = 0;
// first 最短距离 second顶点编号
pq.push({0, s});
while(!pq.empty()) {
auto [dis, v] = pq.top(); pq.pop();
if(vis[v]) continue;
vis[v] = 1;
for(const auto &[u, t] : g[v]) {
if(d[u] > d[v] + t) {
d[u] = d[v] + t;
pq.push({d[u], u});
edges[u].clear();
edges[u].push_back({v, t});
} else if(d[u] == d[v] + t) {
edges[u].push_back({v, t});
}
}
}
};
dijkstra(0);
// dp[i] 表示从0到节点i花费最少时间的方案数
vector<int> dp(n, 0);
dp[0] = 1;
auto getMin = [&] (auto &getMin, int s) {
if(dp[s] > 0) return dp[s] % mod;
for(const auto &[u, t] : edges[s]) {
dp[s] += getMin(getMin, u) % mod;
dp[s] %= mod;
}
return dp[s] % mod;
};
return getMin(getMin, n - 1);
}
};
2.直接在Dijkstra中用dp去记录就可以了
点击查看代码
#include "bits/stdc++.h"
#define rep(i, a, n) for (auto i = a; i < (n); ++i) // repeat
#define repe(i, a, n) for (auto i = a; i <= (n); ++i) // repeat and equal
#define revrep(i, a, n) for (auto i = n; i > (a); --i) // reverse repeat
#define revrepe(i, a, n) for (auto i = n; i >= (a); --i)
#define all(a) a.begin(), a.end()
#define sz(a) (int)(a.size());
#define mem(a,b) memset(a,b,sizeof(a))
#define lb(x) ((x) & -(x)) // lowbit
#define pb push_back
#define qb pop_back
#define pf push_front
#define qf pop_front
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
template<class T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
template<typename T>
ostream & operator << (ostream &out,const set<T>&obj){out<<"set(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<typename T>
ostream & operator << (ostream &out,const unordered_set<T>&obj){out<<"unordered_set(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const map<T1,T2>&obj){out<<"map(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<it->first<<": "<<it->second;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const unordered_map<T1,T2>&obj){out<<"unordered_map(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<it->first<<": "<<it->second;out<<")";return out;}
template<typename T1,typename T2>
ostream & operator << (ostream &out,const pair<T1,T2>&obj){out<<"<"<<obj.first<<", "<<obj.second<<">";return out;}
template<typename T>
ostream & operator << (ostream &out,const vector<T>&obj){out<<"vector(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<class A, class B> string to_string(const pair<A, B> &p);
template<class A, class B, class C> string to_string(const tuple<A, B, C> &p);
template<class A, class B, class C, class D> string to_string(const tuple<A, B, C, D> &p);
string to_string(const string &s) { return '"' + s + '"'; }
string to_string(const char *s) { return to_string((string) s); }
string to_string(char c) { return "'" + string(1, c) + "'"; }
string to_string(bool x) { return x ? "true" : "false"; }
template<size_t L> string to_string(const bitset<L> &x) { return x.to_string(); }
template<class A, class T = typename A::value_type> string to_string(const A &v) {
bool first = 1;
string res = "{";
for (const auto &x: v) {
if (!first) res += ", ";
first = 0;
res += to_string(x);
}
res += "}";
return res;
}
template<class A, class B> string to_string(const pair<A, B> &p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template<class A, class B, class C> string to_string(const tuple<A, B, C> &p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
template<class A, class B, class C, class D> string to_string(const tuple<A, B, C, D> &p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
class Solution {
public:
int countPaths(int n, vector<vector<int>>& roads) {
// dijkstra求俩点之间最短距离
ll mod = 1e9 + 7;
vector<ll> d(n, LLONG_MAX);
vector vis(n, 0);
// 记录图
vector<vector<pii>> g(n, vector<pii>{});
for(const auto &road : roads) {
g[road[0]].push_back({road[1], road[2]});
g[road[1]].push_back({road[0], road[2]});
}
// dp[i] 表示从0到节点i花费最少时间的方案数
vector<int> dp(n, 0);
dp[0] = 1;
auto dijkstra = [&] (int s) {
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>> > pq;
d[s] = 0;
// first 最短距离 second顶点编号
pq.push({0, s});
while(!pq.empty()) {
auto [dis, v] = pq.top(); pq.pop();
// if(vis[v]) continue;
// vis[v] = 1;
if(dis > d[v]) continue;
for(const auto &[u, t] : g[v]) {
if(d[u] > d[v] + t) {
d[u] = d[v] + t;
pq.push({d[u], u});
dp[u] = dp[v];
} else if(d[u] == d[v] + t) {
dp[u] = (dp[u] + dp[v]) % mod;
}
}
}
};
dijkstra(0);
return dp[n - 1];
}
};