题目来源
题目描述
题目解析
- 考察迪克拉斯算法
#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);
}