一. 例题
给一个二维数组,一行代表一个节点,第一个表示出发节点的编号,第二个表示到达节点的编号,第三个表示二者之间的权重,求最短路径。
解法一:
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
const int INF = INT_MAX; // 定义一个代表无穷大的常量
void showVec(vector<int> vec)
{
for (auto i : vec){
cout << i << " " ;
}
cout << endl <<endl;
}
void showVec2(vector<vector<int>>& graph)
{
int n = graph.size();
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
cout << graph[i][j] << " ";
}
cout << endl;
}
cout << endl << endl;
}
int prim(vector<vector<int>>& graph) {
int n = graph.size(); // 获取节点的数量
vector<int> dist(n, INF); // 保存顶点到最小生成树的距离
vector<bool> selected(n, false); // 记录顶点是否被选中
int res = 0; // 记录最小生成树的总长度
dist[0] = 0; // 从任意一点开始构建最小生成树
// 遍历n个节点进行最小生成树的构建
for (int i = 0; i < n; i++) {
int minDist = INF; // 保存距离最小生成树最近的顶点的距离
int minDistVertex = -1; // 保存距离最小生成树最近的顶点的索引号
// 在尚未选中的顶点中,选择距离最小生成树最近的顶点
for (int j = 0; j < n; j++) {
if (!selected[j] && dist[j] < minDist) {
minDist = dist[j];
minDistVertex = j;
}
}
selected[minDistVertex] = true; // 将选中的顶点标记为已选
// 更新与选中顶点的相邻顶点的距离
for (int j = 0; j < n; j++) {
// 如果相邻顶点未选中且与选中顶点有边,并且其距离小于当前记录的距离,则更新距离
showVec(dist);
showVec2(graph);
if (graph[minDistVertex][j] != INF && !selected[j] && graph[minDistVertex][j] < dist[j]) {
dist[j] = graph[minDistVertex][j];
}
}
}
// 计算最小生成树的总长度
for (int i = 0; i < n; i++) {
res += dist[i];
}
return res; // 返回最小生成树的总长度
}
int main() {
int n;
cin >> n; // 输入节点的数量
vector<vector<int>> graph(n, vector<int>(n, INF)); // 创建一个邻接矩阵,初始距离都为无穷大
// 输入节点之间的连接关系
for (int i = 0; i < n * (n - 1) / 2; i++) {
int u, v, length;
cin >> u >> v >> length;
u--; // 顶点编号从1开始,转变为从0开始
v--;
graph[u][v] = graph[v][u] = length; // 无向图,两个方向都要设置距离
}
showVec2(graph);
int minLen= prim(graph); // 执行prim算法得到最小生成树的总长度
cout << minLen<< endl; // 输出最小生成树的总长度
return 0;
}
解法二
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
struct Edge;
struct Node{
public:
Node(int val, int in = 0, int out = 0)
:_val(val)
,_in(in)
,_out(out){}
bool operator()(const Node& a, const Node& b){
return a._val < b._val;
}
bool operator<(const Node& other){
return this->_val < other._val;
}
public:
int _val;
int _in;
int _out;
unordered_set<shared_ptr<Node>> _nextNodes;
unordered_set<shared_ptr<Edge>> _nextEdges;
};
struct Edge{
public:
Edge(int weight,shared_ptr<Node> from = nullptr, shared_ptr<Node> to = nullptr)
:_weight(weight)
,_fromNode(from)
,_toNode(to)
{}
bool operator()(const Edge& a, const Edge& b)const{
return a._weight < b._weight;
}
bool operator<(const Edge& other)const{
return this->_weight < other._weight;
}
public:
int _weight;
shared_ptr<Node> _fromNode;
shared_ptr<Node> _toNode;
};
class Graph{
public:
Graph(vector<vector<int>> data){
create(data);
}
void create(vector<vector<int>> data);
int PrimMST();
private:
void showmap();
public:
map<int, shared_ptr<Node>> _graphNodes;
set<shared_ptr<Edge>> _graphEdges;
};
void Graph::showmap(){
for (auto m : _graphNodes){
//cout << "key = " << m.first << " value = " << endl;
printf("key = %d, value = %p\n", m.first, m.second.get());
}
}
void Graph::create(vector<vector<int>> data){
if (data.empty()){
return;
}
for (auto node : data){
int from = node[0];
int to = node[1];
int weight = node[2];
cout << "from = " << from << " to = " << to << " weight = " << weight << endl;
if (this->_graphNodes.find(from) == this->_graphNodes.end()){
//Node* fromNode = new Node(from);
shared_ptr<Node> fromNode(new Node(from));
this->_graphNodes.insert(make_pair(from, fromNode));
}
if (this->_graphNodes.find(to) == this->_graphNodes.end()){
//Node* toNode = new Node(to);
shared_ptr<Node> toNode(new Node(to));
this->_graphNodes.insert(make_pair(to, toNode));
}
auto fromNode = this->_graphNodes.find(from)->second;
auto toNode = this->_graphNodes.find(to)->second;
shared_ptr<Edge> newEdge(new Edge(weight, fromNode, toNode));
fromNode->_out++;
toNode->_in++;
fromNode->_nextNodes.insert(toNode);
fromNode->_nextEdges.insert(newEdge);
this->_graphEdges.insert(newEdge);
}
showmap();
cout << endl;
}
int Graph::PrimMST(){
if (this->_graphEdges.empty()){
return 0;
}
unordered_set<shared_ptr<Edge>> result;
set<shared_ptr<Node>> myset;
priority_queue<shared_ptr<Edge>> myQueue;
for (auto node : this->_graphNodes){
if (myset.find(node.second) == myset.end()){
myset.insert(node.second);
}
for (auto edge : node.second->_nextEdges){
myQueue.push(edge);
}
while (!myQueue.empty()){
auto edge1 = myQueue.top();
myQueue.pop();
auto toNode = edge1->_toNode;
if (myset.find(toNode) == myset.end()){
myset.insert(toNode);
result.insert(edge1);
for (auto nextedge : toNode->_nextEdges){
myQueue.push(nextedge);
}
}
}
}
int res = 0;
for (auto i : result){
cout << "weight = " << i->_weight << endl;
res += i->_weight;
}
return res;
}
void test(){
vector<vector<int>> data{{1,2,5},{1,3,6},{2,3,7}};
Graph graph(data);
int result = graph.PrimMST();
cout << "result = " << result << endl;
}
int main(void){
test();
}