前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode 1786. 从第一个节点出发到最后一个节点的受限路径数(迪杰斯特拉 + 拓扑排序)

LeetCode 1786. 从第一个节点出发到最后一个节点的受限路径数(迪杰斯特拉 + 拓扑排序)

作者头像
Michael阿明
发布2021-09-06 10:11:04
5150
发布2021-09-06 10:11:04
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

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) 表示节点 nx 之间路径的最短距离

受限路径 为满足 distanceToLastNode(zi) > distanceToLastNode(zi+1) 的一条路径,其中 0 <= i <= k-1 。

返回从节点 1 出发到节点 n 的 受限路径数

由于数字可能很大,请返回对 10^9 + 7 取余 的结果。

示例 1:

代码语言:javascript
复制
输入: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:

代码语言:javascript
复制
输入: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 开始的最短路径是递减的 新图,同时记录节点的入度
  • 采用 拓扑排序,累积前一个节点转移过来的方案数
代码语言:javascript
复制
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 的最短距离 dis
        vector<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阿明),一起加油、一起学习进步!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/03/07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档