#include<cstdio>
#include <vector>
using namespace std;
//求最小生成树——Prim算法——从一点出发逐步扩散求解
//1、伪代码
prim(G,d[])
{
初始化;
for(循环n次)
{
u=使d[u]最小的还未被访问的顶点的编号;
记u以访问;
for(从u出发能到达的所有顶点v)
{
if(v未被访问&&以u为中介点使得v与集合s的最短距离d[v]更优)
{
将G[u][v]赋值给v与集合s的最短距离d[v];
}
}
}
}
//2、代码
const int maxv=1020;
const int INF=0x3fffffff;
//邻接矩阵版
int n,G[maxv][maxv];
int d[maxv]; //顶点与集合s的最短距离
bool vis[maxv]={false};
int prim() //默认0号为初始点,函数返回最小生成树的边权之和
{
fill(d,d+maxv,INF);
d[0]=0;
int ans=0; //记录最小生成树的边权之和
for(int i=0;i<n;++i)
{
int u=-1,min=INF; //u使d[u]最小,min记录最小的d[u]
for(int j=0;j<n;++j)
{
if(vis[j]==false&&d[j]<min)
{
u=j;
min=d[j];
}
}
if(u==-1)
{
return -1;
}
vis[u]=true;
ans+=d[u];//将与集合s距离最小的边权加入最小生成树
for(int v=0;v<n;++v)
{
//v未被访问&&以u为中介点使得v与集合s的最短距离d[v]更优
if(vis[v]==false&&G[u][v]!=INF&&G[u][v]<d[v]) //注意此处与dijkstra算法区别
{
d[v]=G[u][v]; //将 G[u][v]赋值给 d[v]
}
}
}
return ans;
}
//邻接表版
struct node{
int v,dis;
};
vector<node> Adj[maxv];
int n;
int d[maxv];
bool vis[maxv] ={false};
int prim()
{
fill(d,d+maxv,INF);
d[0]=0;
int ans=0; //记录最小生成树的边权之和
for(int i=0;i<n;++i)
{
int u=-1,min=INF; //u使d[u]最小,min记录最小的d[u]
for(int j=0;j<n;++j) //找到未访问顶点中d[]最小的
{
if(vis[j]==false&&d[j]<min)
{
u=j;
min=d[j];
}
}
if(u==-1)
{
return -1;
}
vis[u]=true;
ans+=d[u];//将与集合s距离最小的边权加入最小生成树
//只有下面与邻接矩阵写法有异
for(int j=0;j<Adj[u].size();++j)
{
int v=Adj[u][j].v; //通过邻接表获得u能到达的顶点v
//v未被访问&&以u为中介点使得v与集合s的最短距离d[v]更优
if(vis[v]==false&&Adj[u][j].dis<d[v]) //注意此处与dijkstra算法区别
{
d[v]=Adj[u][j].dis; //将 Adj[u][j].dis赋值给 d[v]
}
}
}
return ans;
}