prim最小生成树

#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:
		int primMinTree(const vector<vector<int> > & matrix){
			int n = matrix.size();
			if(n == 0) return 0;
			vector<bool> book(n,false);//当前顶点是否已经选入树中
			vector<int> dis(n,INT_MAX);//存放当前树到顶点的最小距离
			for(int i = 0;i < n;++i){//第一次以顶点0为树中第1个点
				dis[i] = matrix[0][i];
			}
			dis[0] = 0;
			book[0] = true;//0号顶点选中
			int count = 1;//记录已经找到了多少个顶点,初值为1,表示顶点0已经是找到的
			int sum = 0;//记录路径和
			while(count < n){
				int minW = INT_MAX;//记录一轮找到的最下距离
				int minV = -1;//找到的最小距离对于的 顶点
				for(int i = 1;i < n;++i){//找剩余的最小距离及对于的顶点
					if(!book[i] && dis[i] < minW){
						minW = dis[i];
						minV = i;
					}
				}
				book[minV] = true;
				sum += minW;
				for(int i = 1;i < n;++i){//通过minV更新树到剩余节点的最短距离
					if(!book[i]){
						if(matrix[minV][i] < dis[i]){
							dis[i] = matrix[minV][i];
						}
					}
				}
				++count;
			}
			return sum;
		}
};

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();
	cout << sl.primMinTree(matrix) << endl;
}
int main(){
	test();
	return 0;
}

//输入数据1
//顶点编号从0开始
#if 0
6 10
0 1 4
0 4 1
0 5 2
1 2 6
1 5 3
2 3 6
2 5 5
3 4 4
3 5 5
4 5 3
#endif
//输入结果应为:15

//输入数据2
//顶点编号从1开始
#if 0
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
#endif
//输出结果应为:19

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值