Prim算法
思想:
prim算法对图G(V,E)设置集合S,存放已被放访问的顶点,然后对每次从V-S中选择与集合S的最短距离最小的顶点(为u),访问并加入集合S。之后,令顶点u为中介点,优化所有从u能到达的顶点v与集合S之间的最短距离。这样执行n次,直到集合S已包含所有顶点。
具体实现:
prim算法需要实现两个关键的概念,即集合S的实现、顶点Vi(0≤i≤n-1)与集合S的最短距离
集合S的实现方法:
用一个bool型数组vis[]表示顶点是否已被访问。其中vis[i]==true表示顶点Vi未被访问
顶点与集合S的最短距离:
令int型数组d[]来存放顶点Vi(0≤i≤n-1)与集合S的最短距离。初始时除了起点s的d[s]赋为0,其余顶点都赋为一个很大的数来表示inf,即不可达。
以下是核心代码思想:
const int maxv=1000;//最大顶点数
const int inf=100000000;//设inf为一个很大的数
struct node{
int v,dis; //v为边的目标顶点,dis为边权
};
vector<node> adj[maxv];//图G,adj存放从顶点u出发可以到达的所有顶点
int n;//n为顶点数
int d[maxv];//顶点与集合S的最短距离
bool vis[maxv]={false};//标记数组,vis[i]==true表示已访问
intprim(){//默认0号为初始点,函数返回最小生成树的边权之和
fill(d,d+maxv,inf);//fill函数将整个d数组赋为inf
d[0]=0;//只有0号顶点到集合s的距离为0,其余为inf
int ans=0;//存放最小生成树边权之和
for(int i=0;i<n;i++){//循环n次
int u=-1,min=inf;//u为到最小点的编号,min存放该最小点的边权
for(int j=0;j<n;j++){
if(vis[j]==false&&d[j]<min){//找到未访问的顶点中d[]最小的
u=j;
min=d[j];
}
}
//找不到小于inf的d[u],则剩下的顶点和集合S不连通
if(u==-1)return -1;
vis[u]=true;//标记u为已访问
ans+=d[u];//将与集合S距离最小的边加入最小生成树
for(int j=0;j<adj[u].size();j++){
int v=adj[u][j].v;//通过邻接表直接获得u能到达的顶点v
if(vis[v]==false&&adj[u][j].dis<d[v]){
//如果v未访问&&以u未中介点可以使v离集合s更近
d[v]=adj[u][v].dis;//将g[u][v]赋值给d[v]
}
}
}
return ans;//返回最小生成树的边权之和
}