# include<iostream>
# include<cstring>
using namespace std;
# define inf 0x3f3f3f3f
# define nil -1
const int maxn=100+5;
typedef struct arcnode{
int adjnode;
int weight; //边的权重
arcnode *nextarc;
}arcnode;
typedef struct vnode{
int data; //顶点信息
arcnode *firstarc;
}vnode;
typedef struct graph{
vnode vertexs[maxn];
int vertexnum;
int edgenum;
}graph;
struct closeedge {
int adjvex;
int lowcost;
};
int find(graph g,int v)
{
for(int i=0;i<g.vertexnum;i++)
if(g.vertexs[i].data==v)
return i;
return -1;
}
void init(graph &g) //建图,并初始化
{
cin>>g.vertexnum>>g.edgenum;
for(int i=0;i<g.vertexnum;i++)
{
cin>>g.vertexs[i].data;
g.vertexs[i].firstarc=NULL;
}
for(int i=0;i<g.edgenum;i++)
{
int u,v,w;
cin>>u>>v>>w;
int index_u=find(g,u);
int index_v=find(g,v);
arcnode *s=new arcnode();
s->adjnode=index_v;
s->weight=w;
s->nextarc=g.vertexs[index_u].firstarc;
g.vertexs[index_u].firstarc=s;
arcnode *p=new arcnode();
p->adjnode=index_u;
p->weight=w;
p->nextarc=g.vertexs[index_v].firstarc;
g.vertexs[index_v].firstarc=p;
}
}
int makeit(graph g,int u,int i) //如果有从u->i的无向边,则返回对应权值,否则返回最大值
{
arcnode *s;
s=g.vertexs[u].firstarc;
while(s)
{
if(s->adjnode==i)
return s->weight;
s=s->nextarc;
}
return inf;
}
int minedge(closeedge *w,graph g) //取最小边的索引
{
int index_min;
int min_cost=inf;
for(int i=0;i<g.vertexnum;i++)
{
if(w[i].lowcost>0&&min_cost>w[i].lowcost) //w[i].lowcost=0表示该顶点已加入最小生成树的顶点集合中。
{
min_cost=w[i].lowcost;
index_min=i;
}
}
return index_min;
}
void prim(graph g,int u,closeedge *w)
{
int index_u=find(g,u);
for(int i=0;i<g.vertexnum;i++) //初始化,初始顶点到各个顶点的距离
{
if(i!=index_u)
{
w[i].adjvex=u;
w[i].lowcost=makeit(g,index_u,i);
}
}
w[index_u].lowcost=0; //加入生成树顶点集合
for(int i=1;i<g.vertexnum;i++)
{
index_u=minedge(w,g);//取最小边的索引
cout<<"(v"<<w[index_u].adjvex<<",v"<<g.vertexs[index_u].data<<") ";
w[index_u].lowcost=0; //加入生成树顶点集合
for(int j=0;j<g.vertexnum;j++) //加入以index_u为索引的顶点,并更新w数组,在
{
int m=makeit(g,index_u,j); //得到index_u到j的权值
if(m<w[j].lowcost) //比较,并更新
{
w[j].adjvex=g.vertexs[index_u].data;
w[j].lowcost=m;
}
}
}
}
int main()
{
int u;
closeedge w[maxn];
graph g;
init(g);
cin>>u;
prim(g,u,w);
return 0;
}
总结:
(1)在最小生成树未建成时,一直在维护两个顶点集合,一个是生成树顶点集合s1,另一个是图中的顶点但未在生成树顶点集合中的集合s2,每次都需要从s2中挑出一个到s1的某个顶点的边的权值最小值的顶点加入s1;