0
点赞
收藏
分享

微信扫一扫

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

眼君 2022-01-24 阅读 51

题目(困难)

题目太长放链接
力扣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 条评论