#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <fstream>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include "MinHeap.h"
#define MAX 0xfffff
using namespace std;
unsigned n, m;//假设最多10个顶点
vector<vector<int>> e = {
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
vector<int>(11),
};//邻接矩阵
vector<Node> dis(10);//源点1到其他所有点的最短距离
vector<PreNode> pre(10);//前趋节点
vector<bool> book(10);//标志数组,区别dis的P,Q集合
/*
CLion 使用提示 :
批量注释代码 => Ctrl + shift + /
格式化代码 => option + command + L
补全语句 => Shift + command + return
生成构造器,getter和setter方法等 => control + return
行注释 => control + /
块注释 => control + shift + c
*/
/*
* 输出顶点i的最短路径
*/
void printSolution(unsigned index){
stack<int> s;
int i=n;
if (2<=index&&index<=n) {
while (index!=0){
s.push(index);
index=pre[index].preIndex;
}
}
printf("路径{");
while (!s.empty()){
printf("%u " , s.top());
s.pop();
}
printf("}\n");
}
void print(){
for (int i = 2; i <= n; ++i) {
printSolution(i);
}
}
void solution() {
int T,p1,p2,cost;
printf("请输入一个数T,代表运行算法T次\n");
scanf("%d", &T);
while (T--) {
printf("请输入顶点个数和边数\n");
scanf("%d %d", &n, &m);
/*
*
*/
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
e[i][j] = e[j][i] = (i == j ? 0 : MAX);//自己到自己是0花费,否则先假设为∞距离
}
}
/*
* 读入边权值,假设无向图,则e[p1][p2]都有相同都耗费
*/
for (int i = 1; i <= m; ++i) {
printf("请输入第%d条边(A,B,cost)路程耗费\n",i);
scanf("%d %d %d" , &p1 ,&p2 , &cost);
e[p1][p2]=e[p2][p1]=cost;//无向图
}
dis[1].cost=0;
dis[1].curNode=1;
pre[1].curNode=1;
pre[1].preIndex=0;//很重要,防止死循环!!
for (int i = 2; i <= n; ++i) {
dis[i].cost=e[1][i];
dis[i].curNode=i;//v1对应1号点,v2对应2号点,v3对应3号点
if (dis[i].cost!=MAX) {
pre[i].preIndex=1;//开始的时候假设都是1到其余各点,所以如果有边的关系,则前趋节点就是1
pre[i].curNode=i;//v1则是1,v2则是2
} else{
pre[i].preIndex=-1;//无边则设置为-1
pre[i].curNode=i;//v1则是1,v2则是2
}
book[i]= false;
}
book[1]=true;
MinHeap heap(dis,n);//构造最小堆
while (!heap.empty()){
Node min_cost = heap.top();//每次取出最小的cost的顶点
for (int i = 2; i <= n; ++i) {
if (e[min_cost.curNode][i]<MAX&&
((dis[min_cost.curNode].cost+e[min_cost.curNode][i])<dis[i].cost)) {
pre[i].preIndex=min_cost.curNode;
dis[i].cost=dis[min_cost.curNode].cost+e[min_cost.curNode][i];
}
}
heap.pop();
}
print();
}
}
int main() {
solution();
return 0;
}
/*
1
5 6
1 2 7
1 3 14
2 4 2
3 4 3
3 5 4
4 5 1
*/
头文件在下面这里:👇
//
// Created by 何维刚 on 2021-04-25.
//
#pragma once
#ifndef DIJIESITELA_MINHEAP_H
#define DIJIESITELA_MINHEAP_H
#include <vector>
using namespace std;
struct PreNode{
unsigned curNode;//节点v1则是1,v2则是2
int preIndex;//该节点的前趋节点
PreNode(unsigned _curNode=0, int _preIndex=-1):curNode(_curNode),preIndex(_preIndex){}
};
struct Node {
unsigned curNode;
unsigned cost;
Node(unsigned _curNode = 0, unsigned _cost = 0) : curNode(_curNode), cost(_cost) {}
Node &operator=(const Node &N) {
if (&N == this) {
return *this;
}
this->curNode = N.curNode;
this->cost = N.cost;
return *this;
}
friend ostream &operator<<(ostream &os, const Node &N) {
printf("(curNode:%u,cost:%u)\n", N.curNode, N.cost);
return os;
}
};
class MinHeap {
public:
vector<Node> v;
unsigned curSize, n;
MinHeap(const vector<Node> &vv,int n);
Node &top();
void pop();
void push(const Node &x);
void percolateDown(int i);
bool empty() const;
void buildHeap();
Node &deleteMin();
};
MinHeap::MinHeap(const vector<Node> &vv,int n) : v(n), curSize(n-1) {
for (int i = 0; i <= n-2; ++i) {
v[i + 1] = vv[i+2];
}
buildHeap();
}
Node &MinHeap::top() {
return v[1];
}
void MinHeap::pop() {
if (empty()) {
printf("Error in pop empty heap!!\n");
return;
}
v[1] = v[curSize--];
percolateDown(1);
}
void MinHeap::push(const Node &x) {
if (curSize == v.size() - 1) {
v.resize(v.size() * 2);
}
int hole = ++curSize;
for (; hole > 1 && x.cost < v[hole / 2].cost; hole /= 2)
v[hole] = v[hole / 2];
v[hole] = x;
}
void MinHeap::percolateDown(int hole) {
int child;
Node tmp = v[hole];
for (; hole * 2 <= curSize; hole = child) {
child = hole * 2;
if (child != curSize && v[child + 1].cost < v[child].cost) {
child++;
}
if (v[child].cost < tmp.cost) {
v[hole] = v[child];
} else {
break;
}
}
v[hole] = tmp;
}
bool MinHeap::empty() const {
return curSize == 0;
}
void MinHeap::buildHeap() {
for (int i = curSize / 2; i >= 1; --i) {
percolateDown(i);
}
}
#endif //DIJIESITELA_MINHEAP_H