【Dijkstra】个人练习-Leetcode-882. Reachable Nodes In Subdivided Graph

文章介绍了LeetCode上的一道题目,要求在给定的图中,计算从节点0出发,在最大步数内可以到达(包括细分点)的节点总数。首先尝试使用DFS解决,但部分测试用例未通过,然后采用Dijkstra算法,计算从0到所有节点的最短距离,再计算可达的原节点和细分节点总数。
摘要由CSDN通过智能技术生成

题目链接:https://leetcode.cn/problems/reachable-nodes-in-subdivided-graph/

题目大意:给出一个图,给出所有边及其细分情况edges[],在每个边中插入cnt_i个细分点。给出移动最大步数maxMoves,求从0节点开始,在最大步数内,能够访问到的节点(包括原来的节点和细分节点)的数量。

思路:DFS做,到达一个原节点就减去一定步数,并将剩余步数传递,做下一步的DFS。如果步数不够,那么就记录从这个点到邻居点能够走的步数(也就是细分节点的数量)。最后将访问到的原节点和细分节点数相加。但开始时没考虑先算出到每个原节点的最短距离,而是单纯靠着步数去做,还有些测试点过不了。

单纯DFS代码

class Solution {
public:
    vector<vector<int>> dis;
    vector<vector<int>> mv;
    vector<vector<int>> adj;
    vector<bool> known;

    void DFS(int last, int node, int move) {
        // if (known[node])
        //     return;

        known[node] = true;
        if (move == 0)
            return;
        
        for (auto neb : adj[node]) {
            if (neb != last) {
                if (mv[node][neb] + mv[neb][node] < dis[node][neb]-1 || dis[node][neb] == 1) {
                    if (move >= dis[node][neb]) {
                        mv[node][neb] = dis[node][neb]-1;
                        DFS(node, neb, move - dis[node][neb]);
                    }
                    else
                        mv[node][neb] = max(mv[node][neb], move);
                }
            }
        }

        return;
    }

    int reachableNodes(vector<vector<int>>& edges, int maxMoves, int n) {
        const int MAXD = 0x7FFFFFFF;
        dis.resize(n, vector<int>(n, MAXD));
        mv.resize(n, vector<int>(n, 0));
        adj.resize(n, vector<int>(0));
        known.resize(n, false);

        for (auto e : edges) {
            int u = e[0], v = e[1], cnt = e[2];
            dis[u][v] = dis[v][u] = cnt+1;
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
        
        DFS(-1, 0, maxMoves);
        int ret = 0;
        for (int i = 0; i < n; i++)
            ret += known[i];
        for (auto e : edges) {
            int u = e[0], v = e[1], cnt = e[2];
            if (mv[u][v] + mv[v][u] < dis[u][v])
                ret += mv[u][v] + mv[v][u];
            else
                ret += dis[u][v]-1;
        }

        return ret;
    }
};

题解基本上都是Dijkstra做,先得出从0到所有原节点所需的最少步数,随后将能访问到的原节点和细分节点数加起来。

完整代码

class Solution {
public:
    vector<int> dist;
    vector<vector<pair<int, int>>> G;

    void Dij(int start) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
        pq.emplace(0, start);
        while (!pq.empty()) {
            auto [d, x] = pq.top();
            pq.pop();
            if (d > dist[x])
                continue;
            for (auto [neb, neb_d] : G[x]) {
                int tmp_d = dist[x] + neb_d;
                if (tmp_d < dist[neb]) {
                    dist[neb] = tmp_d;
                    pq.emplace(tmp_d, neb);
                }
            }
        }
    }

    int reachableNodes(vector<vector<int>>& edges, int maxMoves, int n) {
        const int MAXD = 0x7FFFFFFF;
        G.resize(n);
        dist.resize(n, MAXD);

        for (auto e : edges) {
            int u = e[0], v = e[1], cnt = e[2];
            G[u].emplace_back(v, cnt+1);
            G[v].emplace_back(u, cnt+1);
        }

        dist[0] = 0;

        Dij(0);

        int ret = 0;
        for (auto d : dist) {
            if (d <= maxMoves)
                ret++;
        }

        for (auto e : edges) {
            int u = e[0], v = e[1], cnt = e[2];
            int u2v = max(maxMoves - dist[u], 0);
            int v2u = max(maxMoves - dist[v], 0);
            ret += min(v2u + u2v, cnt);
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值