建信金融科技力扣专场竞赛C——链式前向星+dfs路径输出

建信03. 地铁路线规划

题目

某城市有若干条地铁线路,lines 记录了每条地铁线路依次停靠的站点(每条线路均是双向的)
李林想从站点 start 出发前往 end,请规划一条可行路线使得他可以以最小的换乘次数到达目的站点。若有多条路线满足要求,请返回字典序最小的路线(要求路线上无重复的站点)。

注意:

输入数据保证存在 start 到 end 的路线
任意路线上的点在该条路线上仅出现一次(即任意一条路线均不是环线)
示例 1:

输入:lines = [[1,2,3,4,5],[2,10,14,15,16],[10,8,12,13],[7,8,4,9,11]], start = 1, end = 7

输出:[1,2,3,4,8,7]

解释:路线如图所示
从站点 1 到站点 7 的最少换乘 1 次,路线为 [1,2,3,4,8,7]
image.png

示例 2:

输入:lines = [[1,2,3,4,5,6,7,8,9,10,11],[12,13,2,14,8,15],[16,1,17,10,18]], start = 9, end = 1

输出:[9,8,7,6,5,4,3,2,1]

解释:路线如图所示
从站点 9 到站点 1 的最少换乘 0 次,路线为 [9,8,7,6,5,4,3,2,1]
image.png

提示:

1 <= lines.length, lines[i].length <= 100
1 <= lines[i][j], start, end <= 10000

思路:
采用链式前向星建图,深度优先搜索最少换乘,可以采用vector记录路径。时间复杂度有点高,期待大佬们给点意见。代码如下:

class Solution {
public:
    const static int N = 10005;
    int minx = 0x3f3f3f3f;
    
    struct node{
        int to;
        int next;
        int kind;	//表示地铁线
    }edge[N];
    
    vector<int> path,target;
    
    int head[N],book[N] = {0},kind = 0,cnt = 0,endd = 0;
    
    void add_edge(int u,int v,int kind){
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        edge[cnt].kind = kind;
        head[u] = cnt++;
    }
    
    void dfs(int start,int kind,int kinds){
     
        if(kinds > minx){
            return ;   //减枝
        }
        
        if(start == endd){
            if(minx > kinds){
                 target.assign(path.begin(),path.end());
                 minx = kinds;
                 return;
            }
            for(int i = 0; i < path.size() && i < target.size(); ++i){
                if(target[i] < path[i]) return;  //还是原来的字典序小
                if(target[i] > path[i]) break;
            }
            target.assign(path.begin(),path.end());
            minx = kinds;
            return;
        } else {
                 for(int i = head[start]; i != -1; i = edge[i].next){
                if(!book[edge[i].to]){
                    book[edge[i].to] = 1;
                    path.push_back(edge[i].to);
                    if(edge[i].kind != kind && kind != 0){   //种类不一样加1
                        dfs(edge[i].to,edge[i].kind,kinds + 1);
                    }else{  //种类一样不变
                        dfs(edge[i].to,edge[i].kind,kinds);
                    }
                    book[edge[i].to] = 0;   //回溯
                    path.pop_back();
                }
            }
        }    
    }
    
    vector<int> metroRouteDesignI(vector<vector<int>>& lines, int start, int end) {
        endd = end;
        memset(head,-1,sizeof(head));
        for(const auto& row : lines){
            ++kind;
            for(int i = 1; i < row.size(); ++i){
                add_edge(row[i - 1],row[i],kind);
                add_edge(row[i],row[i - 1],kind);
            }
        }
        book[start] = 1;
        path.push_back(start);
        dfs(start,0,0); 
        return target;
    }
};

没接触力扣之前都不知道c++也有public,private这些,学的太浅了哎。
这题刚好复习了链式前向星,之前对链式前向星都只停留在会用的阶段,这次算是理解了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值