Kruskal算法
它把每条边排序,然后依次选取权值最小的边,当然,这个边必须能够带来一个新的顶点,如何判断是新顶点还是老顶点呢?很简单,用并查集把已选取的点放在一个集合里,未选取的点各自为营,选边的时候只需要判断一下,f[pre(e[i].u)]==f[pre[e[i].v]] (第一条边一定在集合里)因为只有两种集合,一种是被选中的,另一种没有
这思想算是一种贪心吧!
prim算法
它像Dijkstra一样有一个dist数组,用来记录主对象和其他对象的距离,与Dijkstra不同的是Dijkstra的主对象是一个固定的点,而prim算法的dist数组主对象是一颗在不断增加顶点的生成树。
随便从一个顶点出发,把他与其他点的距离作为dist(之所以可以随便从一个点出发是因为图的生成树要求图里的每一个它点都要有),然后不断找离dist最近的顶点(和Dijkstra一样挑中了就定下来了,这里 意味着它成为了最小生成树里的顶点),来更新它于其他对象的距离,接着继续找离dist最近的顶点,因为每次选的都是离dist最近的点,所以最后整个生成书也是最小的。
//通过最小元素来松弛最小树与其周围非树顶点的边
for (int e = first0[k]; e!=-1; e=next0[e]){//这里用的是静态邻接表,e是离dist最近的顶点
if (w[e] < dist[v[e]] && !book[v[e]]) {//如果能更新dist与其他点的距离而且这个点又没访问过
dist[v[e]] = w[e];//更新距离,至于为什么这个点一定要是没访问过的点,这是因为一旦之前被选中的那些点他们与dist的距离被确定下来了,就像Dijkstra一样
temp.i = v[e], temp.v = dist[v[e]];
hep.push(temp);
}
}