#include <iostream>
#include <vector>
#include <limits.h>
#include <fstream>
#include <sstream>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
class Solution
{
public:
vector<int> dijkstraMinPath(const vector<vector<int> > & matrix,int s){
//s是要计算的点,第1个顶点的编号从0开始
//本函数计算顶点s到其余点的最小路径
int n = matrix.size();
if(n == 0 || s >= n) return vector<int>();
vector<bool> book(n,false);//当前顶点是否已经选择
vector<int> dis(n,INT_MAX);//存放当前顶点到其余顶点最小距离
for(int i = 0;i < n;++i){//第一次以顶点0为树中第1个点
dis[i] = matrix[s][i];
}
dis[s] = 0;
book[s] = true;//s加入选择
int count = 1;//记录已经找到了多少个顶点,初值为1,表示顶点s已经是找到的
while(count < n){
int minW = INT_MAX;//记录一轮找到的最小距离
int minV = -1;//找到的最小距离对应的顶点
for(int i = 0;i < n;++i){//找剩余的最小距离及对于的顶点
if(!book[i] && dis[i] < minW){
minW = dis[i];
minV = i;
}
}
book[minV] = true;//加入选择
for(int i = 0;i < n;++i){//通过minV更新树到剩余节点的最短距离
if(!book[i] && matrix[minV][i] < INT_MAX){
//需要加入matrix[minV][i] < INT_MAX的判断,因为minV至i须连通。
//否则下面的加法会溢出,产生错误的判断
if((dis[minV] + matrix[minV][i]) < dis[i]){
dis[i] = dis[minV] + matrix[minV][i];
}
}
}
++count;
}
return dis;
}
};
vector<vector<int> > createMatrixFromCin(){
int sid = 0;//sid表示startId,表示节点的编号是从1开始还是从0开始。如果是从0开始则为0
string line;
std::getline(std::cin,line);
std::istringstream iss(line);
int n ,m;//n表示顶点数,m表示边数
//读顶点数,边数
iss >> n >> m;
if(iss.bad() || iss.fail()){
cout << "input n,m error" << endl;
return vector<vector<int> >();
}
//构造矩阵
vector<vector<int> > matrix(n,vector<int>(n,INT_MAX));
for(int i = 0 ;i < n;++i){//对角线赋值为0
matrix[i][i] = 0;
}
//读边信息
for(int k = 0;k < m;++k){
string edgeInfoLine;
std::getline(std::cin,edgeInfoLine);
std::istringstream issEdge(edgeInfoLine);
int e1,e2,w;
issEdge >> e1 >> e2 >> w;
if(issEdge.bad() || issEdge.fail()){
cout << "input edge,w error" << endl;
return vector<vector<int> >();
}
matrix[e1-sid][e2-sid] = w;//sid是顶点编号是从0开始还是从1开始
matrix[e2-sid][e1-sid] = w;//无向图,所以两个方向都要存储
}
return matrix;
}
void test(){
Solution sl;
auto matrix = createMatrixFromCin();
auto result = sl.dijkstraMinPath(matrix,0);
for(auto & elem:result){
cout << elem << " ";
}
cout << endl;
}
int main(){
test();
return 0;
}
//输入数据1
//顶点编号从0开始
#if 0
6 8
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
#endif
//计算0号顶点的结果应该为:
//0 1 5 3 4 6
//输入数据2
//顶点编号从1开始
#if 0
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
#endif
//计算第1个顶点
//输出结果应为:
//0 1 8 4 13 17