介绍
最小生成树:无向图中,所有边权之和最小的树。
思想:
prime算法与Dijisktra算法思想相同,只是prime算法用一个集合存放已访问的结点,即构成最小生成树的顶点,而数组 d [ ] 则表示顶点到集合的最短距离。
实现
1.邻接矩阵法
const int maxn=100;
const int INF=1000000000;
int G[maxn][maxn];
bool isin[maxn]={false};
int dis[maxn];
int num;
int prime(){
int sum=0;
fill(dis,dis+maxn,INF);
dis[0]=0;//从0号结点开始
for(int i=0;i<num;i++){
int m=-1,mv=INF;
//开放结点
for(int j=0;j<num;j++){
if(isin[j]==false&&dis[j]<mv){
m=j;
mv=dis[j];
}
}
if(m==-1) return-1;//不连通返回-1
isin[m]=true;
sum+=dis[m];//求最小路径之和
//更新结点
for(int k=0;k<num;k++){
if(isin[k]==false&&G[m][k]!=INF&&G[m][k]<dis[k])
dis[k]=G[m][k];//dis[]表示两结点间的最小距离,而非到根结点的距离
}
}
return sum;
}
2.邻接表法
const int maxn=100;
const int INF=1000000000;
struct node{
int v;
int value;
};
vector<node> table[maxn];
bool isin[maxn]={false};
int dis[maxn];
int num;
int prime(){
int sum=0;
fill(dis,dis+maxn,INF);
dis[0]=0;//从0号结点开始
for(int i=0;i<num;i++){
int m=-1,mv=INF;
//开放结点
for(int j=0;j<num;j++){
if(isin[j]==false&&dis[j]<mv){
m=j;
mv=dis[j];
}
}
if(m==-1) return -1;
isin[m]=true;
sum+=dis[m];//求最小路径之和
//比较结点
for(int k=0;k<table[i].size();k++){
int v=table[i][k].v;//得到结点下标
if(isin[v]==false&&table[i][k].value<dis[v])
dis[v]=table[i][k].value;//dis[]表示两结点间的最小距离,而非到根结点的距离
}
}
return sum;
}
简单应用
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100;
const int INF=1000000000;
int num,road;
int G[maxn][maxn];
bool isin[maxn]={false};
int path[maxn],sum=0;
void prime(){
fill(path,path+maxn,INF);
path[0]=0;
for(int i=0;i<num;i++){
int m=-1,mv=INF;
for(int j=0;j<num;j++){
if(isin[j]==false&&path[j]<mv){
m=j;
mv=path[j];
}
}
if(m==-1) return;
isin[m]=true;
sum+=path[m];
for(int k=0;k<num;k++){
if(isin[k]==false&&G[m][k]!=INF&&G[m][k]<path[k])
path[k]=G[m][k];
}
}
}
int main(){
int v1,v2;
fill(G[0],G[0]+maxn*maxn,INF);
cin>>num>>road;
for(int i=0;i<road;i++){
cin>>v1>>v2>>G[v1][v2];
G[v2][v1]=G[v1][v2];
}
prime();
cout<<sum<<endl;
return 0;
}