力扣2045——到达目的地的第二短时间(BFS+剪枝)

题目(困难)

题目太长放链接
力扣2045——到达目的地的第二短时间

思路

不是最优但好理解;
时间其实和路径长度相关,转化为求次短路径;
时间与路径长度有关,如果当前时间处于红灯,就等到绿灯,然后加上每段路的时间,所以只要求次短路径;
用BFS求最短路径,采用类似层序遍历的方法,每次步长+1,得到最短和次短路径长,并由步长得到时间。
由于时间复杂度太高需要剪枝,对于次短路径,其实无非两种,minstep+1,minstep+2;
其中minstep+2一定存在,就是多一段往返,而minstep+1不一定存在,需要不重复的多走一步;
无论哪种情况,每个节点访问次数不会超过2次,所以统计访问次数进行剪枝;
另外用set去重的保存下一层的节点们,剪掉同层多个节点访问下一层同一节点的多余情况;

代码

class Solution {
public:
    int t, c;
    int needtime(int step) {
        int at = 0;
        for(int i = 1; i <= step; i++) {
            if((at / c) % 2) {
                at += (at / c + 1) * c - at;
            }
            at += t;
        }
        return at;
    }
    int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
        vector<vector<int>> hash(n+1);
        vector<int> vis(n+1);
        vis[1] = 1;
        t = time, c = change;
        for(auto edge : edges) {
            int a = edge[0], b = edge[1];
            hash[a].push_back(b);
            hash[b].push_back(a);
        }
        int step = 0, minstep = 0, ansstep = 0;
        int mintime = 0, anstime = 0;
        queue<int> q;
        q.push(1);
        while(!q.empty()) {
            int nextn = q.size();
            step++;
            unordered_set<int> nextfloor;   //下一层要遍历的节点,set去重
            while(nextn--) {    //层序遍历
                int now = q.front();
                q.pop();
                for(auto next : hash[now]) {
                    if(next == n && minstep == 0) minstep = step;
                    else if(next == n && minstep && step > minstep) ansstep = step; 
                    if(!nextfloor.count(next)) {
                        if(++vis[next] < 3) {
                            nextfloor.insert(next);
                            q.push(next);
                        }
                    }
                }
            }
            if(ansstep) return needtime(ansstep);
        }
        return 0;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值