Prim算法简明
prim(普利姆)算法和Kruskal算法一般用于解决最小生成树问题,网上还有一个Prim+Heap的算法,空间复杂度比较高,但是效率很高。
这里来简要讲一下prim,大致意思就是先取一个点作为树根(随机哪个点都无所谓,因为最终每个点都会在最小生成树内,所以每个点都可以是树根),然后每次选一个距离当前已有生成树最近的一个点加入生成树形成一个新的生成树,如此一来当所有的点都加入生成树之后所得的生成树就一定是最小生成树,这里有运用到贪心的思想,Kruskal也有用到贪心的思想,个人理解和prim不同的是prim贪心的是点集,Kruskal是边集。
光看文字可能有些晦涩,直接结合注释看代码吧,感觉还是挺简单的。
int graph[maxn][maxn],dist[maxn];
bool visit[maxn];
int prime(int cur) //當前的根
{
int index; //用來臨時存儲距离生成树最近点的下标
int sum = 0; //當前树的權值
memset(visit, false, sizeof(visit)); //初始化節點訪問情況
visit[cur] = true; //將根節點加入生成树
for(int i = 0; i < m; i ++){
dist[i] = graph[cur][i]; //dist记录的是树到点i的距离
//将树根cur视为一颗树,将树到未连接点之间的距离存入dist中
}
for(int i = 1; i < m; i ++){
//有m个点时循环m-1次,因为初始时cur这个点已经在生成树内了
int mincost = INF; //初始化最小值為INF
for(int j = 0; j < m; j ++){
if(!visit[j] && dist[j] < mincost){
//如果當前邊的另一個點不在生成樹中而且距離小於mincost
mincost = dist[j];
//更新mincost和其對應邊和點的下標
index = j;
}
}
visit[index] = true; //將當前點加入生成樹
sum += mincost; //最小生成樹的權+=當前生成樹到index點的權
for(int j = 0; j < m; j ++){
if(!visit[j] && graph[index][j] < dist[j]){
//如果新加入的这个点到j点的距离小于当前的树到j点的距离
dist[j] = graph[index][j];
//更新新生成树到j点的距离
}
}
}
return sum; //返回最小生成樹的權值
}