dijkstra单源最短路径

#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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值