【练习时间】2021/3/29
【题目名称】最小生成树——kruskal算法
【适用范围】最小生成树:使树上的所有点的各边权值和最小;最短路径:两顶点之间的权值和最小;
【思路分析】
在所有的边中找到最小的边,判断边上的两点是否位于同一个连通向量
判断方法:并查集
采用双亲表示法,利用数组存储树;
若不是,则连接;否则不连
n个点,循环n-1次
假设图为这样;
则按照Kruskal算法流程如下:
//最小生成树——kruskal算法
/*
在所有的边中找到最小的边,判断边上的两点是否位于同一个连通向量
判断方法:并查集
采用双亲表示法,利用数组存储树;
若不是,则连接;否则不连
n个点,循环n-1次
测试数据:
9 6
0 2 46
3 4 38
0 1 34
4 5 26
3 5 25
2 5 25
0 5 19
2 3 17
1 4 12
*/
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
struct Graph
{
int from;
int to;
int weight;
};
/*建立并查集,双亲孩子表示法
如果存放的数据不是整数,需要建立结构体数组,由于我们存放的是int类型,所以可以不用建立结构体
struct PNode
{
int data;
int parent;
};
*/
int ver_num;
int edge_num;
Graph graph[100];
int ptree[100];//并查集
void CreateGraph()
{
cin>>edge_num>>ver_num;
for(int i=0;i<edge_num;i++)
{
int ver1,ver2,w;
cin>>ver1>>ver2>>w;
graph[i].from=ver1;
graph[i].to=ver2;
graph[i].weight=w;
}
}
//调用c++的sort函数排序,sort(graph,graph+edge_num,SortGraph),其中SortGraph返回类型为bool;
bool SortGraph(Graph a,Graph b)
{
return a.weight<b.weight;
}
//找到结点的根结点
int FindRoot(int v)
{
int t=v;
while(ptree[t]>-1)
t=ptree[t];
return t;
}
void Kruskal()
{
int ver=0;
for(int i=0;i<edge_num&&ver<=ver_num;i++)
{
int rf=FindRoot(graph[i].from);
int rt=FindRoot(graph[i].to);
if(rt!=rf)
{
cout<<graph[i].from<<"--"<<graph[i].to<<"--"<<graph[i].weight<<endl;
ptree[rt]=rf;
ver++;
}
}
}
int main()
{
CreateGraph();
sort(graph,graph+edge_num,SortGraph);
memset(ptree,-1,sizeof(ptree));//初始化ptree的parent都为-1
Kruskal();
return 0;
}