LeetCode 847 - 访问所有节点的最短路径

题目链接https://leetcode-cn.com/problems/shortest-path-visiting-all-nodes/题目:

存在一个由 n 个节点组成的无向连通图,图中的节点按从 0 到 n - 1 编号。给你一个数组 graph 表示这个图。其中,graph[i] 是一个列表,由所有与节点 i 直接相连的节点组成。

返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。

You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list of all the nodes connected with node i by an edge.

Return the length of the shortest path that visits every node. You m力扣ay start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.


输入:graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
输出:4
解释:一种可能的路径为 [0,1,4,2,3]

思路:

寻找最短路径,最直接的想法就是使用BFS。由于从每个顶点出发得到的路径都不一样,所以我们依次从不同顶点开始宽搜。这道题的关键是状态储存:通过利用一个三元组记录状态的信息来达到避免重复访问的效果。其中第一个元素代表此时所处的节点pointnumber,第二个元素代表已经遍历过的节点组合pointbeen,第三个表示距离distance。pointbeen是一个n位的二进制数,其第n位为1代表此时第n个节点已经被遍历过。当且仅当pointbeen每一位都是1的时候达到了终止状态。此外,这道题允许单个节点被访问多次,所以不需要判断某个节点是否未被遍历过。

代码:

class Solution {
public:
    int shortestPathLength(vector<vector<int>>& graph) {
        int answer=INT32_MAX;
        int n=graph.size();

        /* if been[i][j]=1, it means the current situation has been reached */
        vector<vector<int>> been(n,vector<int>(1<<n,INT32_MAX));   //<point_number, point_been>

        /* start from which point? */
        for(int i=0;i<n;i++){
            cout<<"current point is: "<<i<<endl;
            been[i][1<<i]=true; // setting the starting situation..
            queue<tuple<int,int,int>> q;    // <point_number, point_been, distance>
            q.emplace(i,1<<i,0);
            while(!q.empty()){
                auto [point_number,point_been,distance] = q.front();
                q.pop();
                cout<<"the top num is: "<<point_number<<endl;
                if(point_been==(1<<n)-1) {
                    answer=min(answer,distance);
                    cout<<"ans is: "<<answer<<endl;
                    break;
                }
                else for(int point_next: graph[point_number]){
                    //if(point_been>>n==0 && ) : can revisited nodes multiple times
                    int point_been_next=point_been|(1<<point_next);
                    if(distance<been[point_next][point_been_next]){
                        q.emplace(point_next,point_been_next,distance+1);
                        been[point_next][point_been_next]=distance;
                    }
                }
            }
        }
        return answer;
    }
};

收获:

再一次实践中使用了三元组tuple,利用emplace代替push,提高了宽搜的熟练度,利用位运算和二进制记录状态(这个思想和“大航海时代“异曲同工)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值