当前位置: 首页 > news >正文

[leetcode]1786. 从第一个节点出发到最后一个节点的受限路径数(Dijkstra+记忆化搜索/dp)

题目链接

题意

给定一个无向连通图,edges={u,v,w} 表示 u u u v v v之间有一条无向边,边权为 w w w
n n n个点 [ 1 , n ] [1,n] [1,n] 每个点到 n n n的最短路为 d i s [ i ] dis[i] dis[i]
定义受限路径: 从起点 1 1 1 n n n,路径上的 d i s [ i ] dis[i] dis[i]递减
1->n的受限路径方案数

方法一 Dijkstra+记忆化搜索

思路

通过Dijkstra预处理出每个点距离 n n n的最短路
通过dfs枚举每种方案 加上记忆化 避免超时

Code

using ll = long long;
#define pii pair<int,int>
#define ar2 array<ll,2>
void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=1e5+10,MOD=1e9+7,INF=0x3f3f3f3f;const long long LINF=LLONG_MAX;const double eps=1e-6;
int a[N];
class Solution {
public:
    int countRestrictedPaths(int n, vector<vector<int>>& edges) {
        vector<vector<ar2>>g(n+1);
        for(auto e:edges){
            int u=e[0],v=e[1],w=e[2];
            g[u].push_back({w,v});
            g[v].push_back({w,u});
        }

        vector<ll>dis(n+1,LINF);//注意要用LINF,INF太小了
        dis[n]=0;
        priority_queue<pii,vector<pii>,greater<>>pq;
        pq.emplace(0,n);

        while(pq.size()){
            auto [d,i]=pq.top();pq.pop();
            if(d>dis[i]) continue;

            for(auto [w,j]:g[i]){
                if(dis[j]>d+w){
                    dis[j]=d+w;
                    pq.emplace(dis[j],j);
                }
            }
        }
        // if(dis[1]==LINF) return 0;
        for(int i=1;i<=n;i++){
            if(dis[i]==LINF) dis[i]=-1;
        }

        cout<<dis[1]<<endl;

        vector<ll>memo(n+1,-1);
        function<ll(int)>dfs=[&](int i)->ll{
            if(i==n) return 1;
            if(memo[i]!=-1) return memo[i];

            int ret=0;
            for(auto [w,j]:g[i]){
                if(dis[i]>dis[j]){
                    ret=(ret+dfs(j))%MOD;
                }
            }
            // printf("dfs(%d),retrun %d\n",i,ret%MOD);
            memo[i]=ret%MOD;
            return memo[i];
        };
        
        return dfs(1)%MOD;

    }
};

实现细节

  • 注意 Dijkstra要从终点 n n n开始扩展最短路,因为 d i s [ i ] dis[i] dis[i]在此题中表示 i i i n n n的距离,跟常见的Dijkstra不同 不是表示 i i i 1 1 1的距离
    记得开longlong,并且无穷大也要用longlong的max来表示,不然有一个样例过不去

方法二 Dijkstra+dp

思路

思路同上,把记忆化搜索改成dp,我感觉没有记忆化搜索直观,但是能快一点点

Code

using ll = long long;
#define pii pair<int,int>
#define ar2 array<ll,2>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=1e5+10,MOD=1e9+7,INF=0x3f3f3f3f;const long long LINF=LLONG_MAX;const double eps=1e-6;

class Solution {
public:
    int countRestrictedPaths(int n, vector<vector<int>>& edges) {
        vector<vector<ar2>>g(n+1);
        for(auto e:edges){
            int u=e[0],v=e[1],w=e[2];
            g[u].push_back({w,v});
            g[v].push_back({w,u});
        }

        vector<ll>dis(n+1,LINF);
        dis[n]=0;
        priority_queue<pii,vector<pii>,greater<>>pq;
        pq.emplace(0,n);

        while(pq.size()){
            auto [d,i]=pq.top();pq.pop();
            if(d>dis[i]) continue;

            for(auto [w,j]:g[i]){
                if(dis[j]>d+w){
                    dis[j]=d+w;
                    pq.emplace(dis[j],j);
                }
            }
        }
        // if(dis[1]==LINF) return 0;
        for(int i=1;i<=n;i++){
            if(dis[i]==LINF) dis[i]=-1;
        }

        vector<int>idx(n);
        iota(idx.begin(),idx.end(),1);
        sort(idx.begin(),idx.end(),[&](int a,int b){
            return dis[a]<dis[b];
        });//按最短路从小到大排序

        vector<ll>dp(n+1);//dp[i]表示从i到n的方案数
        dp[n]=1;
        for(int i:idx){
            for(auto [_,j]:g[i]){
                if(dis[i]>dis[j]){
                    dp[i]=(dp[i]+dp[j])%MOD;
                }
            }
        }
        
        return dp[1];
    }
};

实现细节

根据最短路从小到大更新dp
因为受限路径要求dp[i]要根据dis小于dis[i]的值更新

http://www.dtcms.com/a/113396.html

相关文章:

  • 私有部署stable-diffusion-webui
  • 44. 评论日记
  • STP学习
  • 【LeetCode】大厂面试算法真题回忆(48)--静态扫描最优成本
  • 为 IDEA 设置管理员权限
  • MYSQL 存储引擎 和 日志
  • 论文阅读笔记:Denoising Diffusion Implicit Models (5)
  • 英伟达Blackwell架构深度拆解:新一代GPU如何突破算力瓶颈?
  • DHCP Snooping 主要作用
  • 【Redis】通用命令
  • 聊聊Spring AI的ChromaVectorStore
  • #SVA语法滴水穿石# (007)关于 $past 的用法
  • P10587 「ALFR Round 2」C 小 Y 的数 Solution
  • Python 如何高效实现 PDF 内容差异对比
  • 房地产之后:探寻可持续扩张的产业与 GDP 新思
  • 在线编辑数学公式
  • NDK开发:音视频处理基础
  • 解释观察者模式,如何实现观察者模式?
  • 单域名 vs 通配符:如何选择最适合你的 SSL 证书?
  • API 类别 - 方法重载
  • JVM虚拟机篇(五):深入理解Java类加载器与类加载机制
  • 纯css实现环形进度条
  • React 零基础学习计划(10节课小项目)
  • STM32定时器通道1-4(CH1-CH4)的引脚映射关系
  • 信创国产化项目验收的标准与流程
  • HBase的安装与简单操作
  • 14.1linux中platform设备驱动实验(知识点)_csdn
  • 关于Linux系统安装和优化的教程
  • Three.js 系列专题 1:入门与基础
  • JetBrains插件市场(附官网地址)