华为机试:最小碰撞时延

题目来源

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目解析

#include <utility>
#include <vector>
#include <map>
#include <set>
#include <iostream>


using namespace std;



class Solution{
    struct Edge;
    struct Node;
    struct Graph;

    struct Node{
        int val;
        int in;
        int out;
        std::vector<Node *> nexts;
        std::vector<Edge *> edges;
        explicit Node(int val, int in = 0, int out = 0) : val(val), in(in), out(out) {
        }
    };

    struct Edge{
        int weight;
        Node *from;
        Node *to;

        Edge(Node *from, Node *to, int weight = 0) : from(from), to(to), weight(weight){
        }
    };

    struct Graph{
        std::map<int, Node *> nodes;
        std::set<Edge*> edges;
    };

private:

// 从所有未走过的路中选出一个最小的节点
    Node *getMinNode( std::map<Node *, int> &disMap, std::set<Node *>& used){
        Node *minNode = nullptr;
        int min = INT_MAX;
        for(auto iter : disMap){
            auto node = iter.first;
            auto dis = iter.second;
            if(used.count(node) == 0 &&dis < min){ // 当前路没有走过&&更进
                min = dis;
                minNode = node;
            }
        }
        return minNode;
    }

    Graph *graph;
public:
    Solution(){
        graph = new Graph();
    }

    // 从start -- > target的最小距离
    int  minDistance(int start, int target){
        if(graph == nullptr || graph->nodes.count(start) == 0 || graph->nodes.count(target) == 0){
            return -1;
        }

        std::map<Node *, int> disMap;
        std::set<Node *> used;
        Node *from = graph->nodes[start];
        disMap[from] = 0;
        auto minNode = getMinNode(disMap, used);
        /*
         * 1. 选出一个最小的节点
         * 2. 然后刷新所有它的邻接点距离
         * 3. 标记当前已经选过 && 回到1
         * */
        while (minNode != nullptr){
            // 刷新
            for(auto e : minNode->edges){
                auto toNode = e->to;
                int currDis = disMap[minNode];
                if(disMap.count(toNode) == 0){ // 之前没有到过这里
                    disMap[toNode] = currDis + e->weight; // 从当前点到这个点的距离是: 之前累加的点 + 当前边的权重
                }else{  // 之前这个点已经来过了:那么看一下是之前的好还是现在的好
                    disMap[toNode] =  std::min(disMap[toNode], currDis + e->weight);
                }
            }
            //
            used.insert(minNode); // 当前节点走完
            minNode = getMinNode(disMap, used);
        }

        return disMap[graph->nodes[target]];
    }

    void addNode(int from, int to, int weight){
        if(graph->nodes.count(from) == 0){
            graph->nodes[from] = new Node(from);
        }
        if(graph->nodes.count(to) == 0){
            graph->nodes[to] = new Node(to);
        }
        auto fNode = graph->nodes[from], tNode = graph->nodes[to];
        auto edge = new Edge(fNode, tNode, weight);
        fNode->out++;
        tNode->in++;
        fNode->nexts.push_back(tNode);
        fNode->edges.push_back(edge);
        graph->edges.insert(edge);
    }
};

int main(){
    Solution a;

    int N , M;
    std::cin >> N >> M;

    for (int i = 0; i < M; ++i) {
        int f, t, w;
        std::cin >> f >> t >> w;
        a.addNode(f, t, w);
    }

    int start, to;
    std::cin >> start >> to;

    std::cout << a.minDistance(start, to);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值