文章目录
- 1. 题目
- 2. 解题
1. 题目
现有一个加权无向连通图。
给你一个正整数 n ,表示图中有 n 个节点,并按从 1 到 n 给节点编号;另给你一个数组 edges ,其中每个 edges[i] = [ui, vi, weighti]
表示存在一条位于节点 ui 和 vi 之间的边,这条边的权重为 weighti 。
从节点 start
出发到节点 end
的路径是一个形如 [z0, z1, z2, ..., zk]
的节点序列,满足 z0 = start 、zk = end
且在所有符合 0 <= i <= k-1 的节点 zi 和 zi+1 之间存在一条边。
路径的距离定义为这条路径上所有边的权重总和。
用 distanceToLastNode(x)
表示节点 n
和 x
之间路径的最短距离。
受限路径 为满足 distanceToLastNode(zi) > distanceToLastNode(zi+1)
的一条路径,其中 0 <= i <= k-1 。
返回从节点 1 出发到节点 n 的 受限路径数 。
由于数字可能很大,请返回对 10^9 + 7 取余 的结果。
示例 1:
输入:n = 5,
edges = [[1,2,3],[1,3,3],[2,3,1],[1,4,2],[5,2,2],[3,5,1],[5,4,10]]
输出:3
解释:每个圆包含黑色的节点编号和蓝色的 distanceToLastNode 值。
三条受限路径分别是:
1) 1 --> 2 --> 5
2) 1 --> 2 --> 3 --> 5
3) 1 --> 3 --> 5
示例 2:
输入:n = 7,
edges = [[1,3,1],[4,1,2],[7,3,4],[2,5,3],[5,6,1],[6,7,2],[7,5,3],[2,6,4]]
输出:1
解释:每个圆包含黑色的节点编号和蓝色的 distanceToLastNode 值。
唯一一条受限路径是:1 --> 3 --> 7 。提示:
1 <= n <= 2 * 10^4
n - 1 <= edges.length <= 4 * 10^4
edges[i].length == 3
1 <= ui, vi <= n
ui != vi
1 <= weighti <= 10^5
任意两个节点之间至多存在一条边
任意两个节点之间至少存在一条路径
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-restricted-paths-from-first-to-last-node
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
- 先预处理出每个点 到 n 点 的最短路径,参考迪杰斯特拉算法
- 再建立 1 开始的最短路径是递减的 新图,同时记录节点的入度
- 采用 拓扑排序,累积前一个节点转移过来的方案数
typedef pair<int, int> pii;
struct cmp{bool operator()(pii& a, pii& b) const{return a.first > b.first;}
};
class Solution {
public:int countRestrictedPaths(int n, vector<vector<int>>& edges) {// 建图,迪杰斯特拉 求解 每个节点到 n 的最短距离 disvector<unordered_map<int,int>> g(n);for(auto & e : edges){g[e[0]-1][e[1]-1] = e[2];g[e[1]-1][e[0]-1] = e[2];}vector<int> dis(n, INT_MAX);priority_queue<pii, vector<pii>, cmp> q;dis[n-1] = 0;q.push({0, n-1});while(!q.empty()){pii tp = q.top();int d = tp.first;int id = tp.second;q.pop();for(auto it = g[id].begin(); it != g[id].end(); ++it){int nid = it->first;int nd = it->second;if(d + nd < dis[nid]){dis[nid] = d + nd;q.push({dis[nid], nid});}}}// 建立 从 1 节点开始的 dis 递减图,并记录入度vector<int> indegree(n, 0);unordered_map<int,unordered_set<int>> g2;queue<int> q1;q1.push(0);unordered_set<int> vis;vis.insert(0);while(!q1.empty()){int id = q1.front();q1.pop();for(auto it = g[id].begin(); it != g[id].end(); ++it){int nid = it->first;if(dis[id] > dis[nid])//递减{g2[id].insert(nid);//建图indegree[nid]++;//记录出入度if(!vis.count(nid))//防止重复记录入度{vis.insert(nid);q1.push(nid);}}}}// 拓扑排序long long mod = 1e9+7;vector<long long> ans(n, 0);ans[0] = 1;queue<int> q2;q2.push(0);while(!q2.empty()){int id = q2.front();q2.pop();for(auto it = g2[id].begin(); it != g2[id].end(); ++it){int nid = *it;ans[nid] = (ans[nid] + ans[id])%mod;if(--indegree[nid] == 0)q2.push(nid);}}return ans[n-1]%mod;}
};
676 ms 174 MB C++
我的CSDN博客地址 https://michael.blog.csdn.net/
长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!