一:prim算法
该算法以顶点为突破口,在最小生成树集合中找寻具有最小对外边权的顶点。并将该边的另一个不在生成树集合的顶点加入最小生成树集合
/**
最小生成树问题(prim算法)
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
8
**/
#include<stdio.h>
#include<iostream>
#define INF 9999999
using namespace std;
int cost[100][100]; //cost[u][v]表示边u,v的权值(不存在的情况下设为INF)
int mincost[100]; //从集合X出发的边到每个顶点的最小权值,,集合X为最小生成树集合,初始化INF
bool used[100]; //标记顶点是否包含在生成树集合X中,初始化为false
int V,E; //V为顶点数,E为边数
int prim(){
for(int i=0;i<V;i++){
mincost[i]=INF;
used[i]=false;
}
mincost[0]=0;
int res=0;
while(true){
int v=-1;
//从不属于X的顶点中选取从X到其权值最小的顶点
for(int u=0;u<V;u++){
if(!used[u]&&(v==-1||mincost[u]<mincost[v])){
v=u;
}
}
if(v==-1){
break;
}
used[v]=true;//把顶点v假如集合X
res+=mincost[v]; //把边的长度加入结果中
for(int u=0;u<V;u++){
mincost[u]=min(mincost[u],cost[v][u]); //更新未加入X集合的顶点到集合的权值
}
}
return res;
}
int main(){
int tempx,tempy,co;
scanf("%d%d",&V,&E);
//边权初始化为INF
for(int i=0;i<V;i++)
for(int j=0;j<V;j++){
cost[i][j]=INF;
}
for(int i=0;i<E;i++){
scanf("%d%d%d",&tempx,&tempy,&co);
cost[tempx][tempy]=co;
cost[tempy][tempx]=co;
}
printf("%d\n",prim());
return 0;
}
二:kruskal算法
该算法按权值将边从从小到大排序,利用并查集原理将边的两个顶点逐渐组建集合,直到将所有顶点加入同一个集合。已经在同一个集合的顶点,不得重复添加
/**
最小生成树问题(kruskal算法)
输入
5 6
0 1 2
1 2 1
2 3 4
3 4 3
0 4 5
0 3 2
输出
8
**/
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct edge{
int u,v,cost;
};
bool comp(const edge& e1,const edge& e2){
return e1.cost<e2.cost;
}
edge es[100]; //存储边的权值
int V,E; //V为顶点数,E为边数
int pre[100];
int find(int x) /*查找祖先节点*/
{
int r=x;
while(pre[r]!=r)
{
r=pre[r];
}
int i=x,j;
while(i!=r) /*压缩路径*/
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
//并查集合并
void join(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
{
pre[a]=b;
}
}
//并查集初始化
void init_union(){
for(int i=0;i<V;i++){
pre[i]=i;
}
}
int kruskal(){
sort(es,es+E,comp);
//并查集初始化
init_union();
int res=0;
for(int i=0;i<E;i++){
edge e=es[i];
//当边的两点不在同一个集合中时合并集合
if(find(e.u)!=find(e.v)){
join(e.u,e.v);
res+=e.cost;
}
}
return res;
}
int main()
{
int from,to,cost;
scanf("%d%d",&V,&E);
//边数为E但需要2*E个存储无向图
//E=E*2;
for(int i=0;i<E;i=i+1){
scanf("%d%d%d",&from,&to,&cost);
es[i].u=from;
es[i].v=to;
es[i].cost=cost;
// es[i+1].v=to;
// es[i+1].u=from;
// es[i+1].cost=cost;
}
printf("%d\n",kruskal());
return 0;
}