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];
    }
};
posted @ 2024-03-05 14:43  57one  阅读(7)  评论(0编辑  收藏  举报