基本思想:(加点)
设G=(V, E)是具有n个顶点的连通网,
T=(U, TE)是G的最小生成树,
T的初始状态为U={u0}(u0∈V),TE={ },
重复执行下述操作:
在所有u∈U,v∈V-U的边中找一条代价最小的边(u, v)并入集合TE,同时v并入U,直至U=V。
伪代码:
算法:Prim
输入:无向连通网G=(V,E)
输出:最小生成树T=(U,TE)
1. 初始化两个辅助数组lowcost=arc[0][i]和adjvex=0(0是始点);
2. 输出顶点u0,将顶点u0加入集合U中;
3. 重复执行下列操作n-1次
3.1 在lowcost中选取最短边(lowcost[k]),取对应的顶点序号k;
3.2 输出顶点k和对应的权值;
3.3 将顶点k加入集合U中(lowcost[k]=0);
3.4 调整数组lowcost和adjvex;
代码实现:
#include<iostream>
using namespace std;
const int Max=10;//图中最多顶点个数
int visited[Max]={0};//全局数组变量visited初始化
class MGraph{
char vertex[Max];//存放顶点的数组
int edge[Max][Max];//存放边的数组
int vertexNum,edgeNum;//顶点数和边数
int MinEdge(int r[],int n);
public:
MGraph(char a[],int n,int e);//构造函数,建立具有n个顶点e条边的图
~MGraph(){};//析构函数为空
void DFT(int v);//深度优先遍历
void BFT(int v);//广度优先遍历
void prim(int v);//prim算法找最小生成树
};
//无权值图的构造函数
/*MGraph::MGraph(char a[],int n,int e){
int i,j,k;//i j边依附的顶点编号
int w;//权值
vertexNum=n;
edgeNum=e;
for(i=0;i<vertexNum;i++)
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
edge[i][j]=0;
for(k=0;k<edgeNum;k++)
{
cin>>i>>j;//输入边依附的两个顶点编号
edge[i][j]=1;edge[j][i]=1;//置有边标志
}
}*/
//有权值图的构造函数
/*MGraph::MGraph(char a[],int n,int e){
int i,j,k;//i j边依附的顶点编号
int w;//权值
vertexNum=n;
edgeNum=e;
for(i=0;i<vertexNum;i++)
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
if(i==j)
edge[i][j]=0;
else
edge[i][j]=100;//边上权的最大值100
for(k=0;k<edgeNum;k++)
{
cin>>i>>j>>w;//输入边依附的两个顶点编号,权值
edge[i][j]=w;edge[j][i]=w;//置有边标志
}
}*/
MGraph::MGraph(char a[],int n,int e){
int i,j,k;//i j边依附的顶点编号
int w;//权值
vertexNum=n;
edgeNum=e;
for(i=0;i<vertexNum;i++)//存储顶点
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)//初始化邻接矩阵
{
for(j=0;j<vertexNum;j++)
{
cin>>w;//输入权值
edge[i][j]=w;
edge[j][i]=w;
}
}
}
int MGraph::MinEdge(int r[],int n)
{
int min=100;//仅记载最小值下标会有bug
int j=0;
for(int i=1;i<n;i++)
{
if(r[i]!=0&&r[i]<min)
{
min=r[i];
j=i;
}
}
return j;
}
void MGraph::DFT(int v)
{
cout<<vertex[v];visited[v]=1;
for(int j=0;j<vertexNum;j++)
if(edge[v][j]==1&&visited[j]==0)
DFT(j);
}
void MGraph::BFT(int v)
{
int w,j,Q[Max];
int front=-1,rear=-1;
cout<<vertex[v];
visited[v]=1;
Q[++rear]=v;
while(front!=rear)
{
w=Q[++front];
for(j=0;j<vertexNum;j++)
if(edge[w][j]==1&&visited[j]==0)
{
cout<<vertex[j];
visited[j]=1;
Q[++rear]=j;
}
}
}
void MGraph::prim(int v)//从顶点v出发
{
int i,j,k;
int adjvex[Max],lowcost[Max];
for(i=0;i<vertexNum;i++)//初始化辅助数组
{
lowcost[i]=edge[v][i];
adjvex[i]=v;
}
lowcost[v]=0;//将顶点v加入到集合
for(k=1;k<vertexNum;k++)//迭代n-1次
{
j=MinEdge(lowcost,vertexNum);//寻找最短边的邻接点j
cout<<lowcost[j]<<" ";
lowcost[j]=0;//顶点j加入到集合
for(i=0;i<vertexNum;i++)//调整辅助数组
if(edge[i][j]<lowcost[i])
{
lowcost[i]=edge[i][j];
adjvex[i]=j;
}
}
}
/*int main()
{
int i;
char ch[]={'A','B','C','D','E','F'};
MGraph MG(ch,6,9);
for(i=0;i<Max;i++)
visited[i]=0;
cout<<"深度:";
MG.DFT(0);
for(i=0;i<Max;i++)
visited[i]=0;
cout<<"广度:";
MG.BFT(0);
MG.prim(0);
return 0;
测试数据,输入边依次为
0 1 34
0 2 46
0 5 19
1 4 12
2 3 17
2 5 25
3 4 38
3 5 25
4 5 26
}*/
int main()
{
int n,m;
cin>>n>>m;
char ch[n];
for(int i=0;i<n;i++)
ch[i]='A'+i;
MGraph MG(ch,n,m);
MG.prim(0);
return 0;
}