用prim算法构建最小生成树适合顶点数据较少而边较多的图(稠密图)
prim算法生成连通图的最小生成树模板伪代码:
G为图,一般为全局变量,数组d为顶点与集合s的最短距离
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];
}
} }
}
邻接矩阵版:
//邻接矩阵版
const int MAXV = ; //最大顶点数
const int INF = ; //设INF为一个很大的数 int n,m, G[MAXV][MAXV]; //n为顶点数,G为图
int d[MAXV]; //顶点与集合S的最短距离
bool vis[MAXV] = { false }; //默认0号为初始点,函数返回最小生成树的边权之和
int prim(){
//初始化
fill(d, d + MAXV, INF);
d[] = ;
int ans = ; //存放最小生成树的边权之和
//遍历所有的顶点,每次遍历访问一个顶点
for (int i = ; i < n; i++){
//找出当前还未访问但是距离集合S最近的顶点
int u = -, MIN = INF;
for (int j = ; j < n; j++){
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} //如果找不到这样的顶点
if (u == -) return -; //标记这个顶点为已访问
vis[u] = true;
ans += d[u]; //遍历这个顶点的邻接点,如果没有访问且距离集合S更近,更新d[u]
for (int j = ; j < n; j++){
if (vis[j] == false && G[u][j] != INF && G[u][j] < d[j]){
d[j] = G[u][j];
}
}
} return ans;
}
邻接表模板:
const int MAXV = ;
const int INF = ; struct Node{
int v, dis; //v为边的目标顶点,dis为权
}; vector<Node> Adj[MAXV];
int n, m;
int d[MAXV];
bool vis[MAXV] = { false }; int prim(){
fill(d, d + MAXV, INF);
d[] = ;
int ans = ; for (int i = ; i < n; i++){
int u = -, MIN = INF;
for (int j = ; j < n; j++){
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} if (u == -) return -;
vis[u] = true;
ans += d[u];
for (int j = ; j < Adj[u].size(); j++){
int v = Adj[u][j].v;
if (vis[v] == false && Adj[u][j].dis < d[v]){
d[v] = Adj[u][j].dis;
}
}
}
return ans;
}