从第一个节点出发到最后一个节点的受限路径数

本文深入探讨了图论中的最短路径问题,重点在于shortestpath后采用的单向梯度下降算法。通过动态规划思想,从源节点递归寻找到达目标节点的最小路径。算法中,利用优先级队列维护节点,并在更新距离矩阵时避免回溯。同时,介绍了路径计数规模的限制,并给出了完整的C++代码实现,包括Dijkstra算法和路径计数函数,用于解决大规模图的最短路径问题。
摘要由CSDN通过智能技术生成

回顾很久之前做的题目,机考说不定真考图论了呢,关键是shortest path后的单向梯度下降算法,注意这里是与结点n之间的距离,不是0

  •  step[i]+=path(t.v,j); 这个包含了动态规划的思想,从源节点的所有路径数,归结为找寻子源节点到n的总路径数
  • 注意题目对路径数的规模限制: 返回对 10^9+7 取余 的结果
long long INF=pow(10,10);
int N=4*pow(10,4);  //最大的结点数
//The line is special for the line that has weight
struct Edge{
    int v,w;
    Edge(int v,int w):v(v),w(w){}
};

struct Node{
    int u,w;//w is set special for the capital point: means the final weight
    Node(){}
    Node(int u,int w):u(u),w(w){}   //初始的w都是没有值的
    bool operator<(const Node &a) const
    {
        return w>a.w;
    }
};


class Solution {
public:
    priority_queue<Node>q; //Why using this? To maintain the Node that added to the V-U is the smallest!
    vector<vector<Edge>>g;//altered Adjacency List
    vector<bool> vis;
    vector<long long> dist; //未加入连通图的结点dist值都是无穷大
    int p; //记录路径的总数
    int countRestrictedPaths(int n, vector<vector<int>>& edges) {
        auto dijkstra=[this](int s){
            //......initialize
            dist[s]=0;
            q.push(Node(s,0));  //第一个结点入队列

            while(!q.empty()){
                Node e=q.top();
                q.pop();
                int u=e.u;
                if(!vis[u]){  //1.访问过都不再访问1
                    vis[u]=true;
                    int num=g[u].size();
                    for(int i=0;i<num;i++){
                        int v=g[u][i].v;//u point's NO.i Adjacency point
                        int c=g[u][i].w;
                        //Sift1
                        if(vis[v])  //2.访问都不再访问2
                            continue;
                        //Sift2: choose to update the dist martrix or not
                        //下面是核心代码部分:
                        if(dist[v]>dist[u]+c){
                            dist[v]=dist[u]+c;
                            q.push(Node(v,dist[v]));  //注意: w是从这里产生值的
                        }
                    }
                }
            }
        };
        p=0;
        g.resize(N);
        dist.resize(n+1);
        fill(dist.begin(),dist.end(),INF);
        vis.resize(n+1);
        fill(vis.begin(),vis.end(),false);

        for(auto &t:edges){
            g[t[0]].push_back(Edge(t[1],t[2]));
            g[t[1]].push_back(Edge(t[0],t[2]));
        }
        dijkstra(n);   //下标从1开始
        vector<int> step(n+1,-1);
        function<int(int,int)> path=[&](int i,int j)->int{  //注意这里的返回值为路径总数
            if(i==j){
                return 1;
            }
            if(step[i]!=-1) return step[i];  //说明前面肯定求过了
            step[i]=0;   //遍历到当前结点,就要初始化为0
            for(auto &t:g[i]){
                if(dist[i]<=dist[t.v])   //因为下坡具有单向性,所以不会回溯
                    continue;
                step[i]+=path(t.v,j);
                if(step[i]>(int)(pow(10,9)+7))
                    step[i]=step[i]%(int)(pow(10,9)+7);
            }
            return step[i];
        };
        return path(1,n);
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值