1.Prim算法
从某个顶点开始,假设v0,设v0在一顶点集合u中, 此时顶点集合u只有一个点v0,选取集合u中的点到与其他点权值最小的一个边, 并将与之相连的点加入集合u, 不断重复此操作, 最后的到一颗最小生成树。
int cost[maxv][maxv] //cost[u][v]表示u, v两点间权值, 两点无边则取INF
int mincost[maxv] //保存最小权值
bool used[maxv] //判断顶点i是否在集合u中
int V;
int prim()
{
for(int i = 0; i < V; i++)
{
mincost[i] = INF;
used[i] = false;
}
mincost[0] = 0;
int res = 0;
while(true)
{
int v = -1;
for(int i = 0; i < V; i++)
if(!used[i] && (v == - 1 || mincost[i] < mincost[v])) v = i;
if(v == - 1) break;
used[v] = true;
res += mincost[v];
for(int i = 0; i < V; i++) //所有选出的点更新mincost,
//得到点集合与非集合中点的距离。之后再从中又选出最小距离
mincost[i] = min(mincost[i], cost[v][i]);
}
}
2.Kruskal
将所有的边按照权值从小到大排序,遍历所有的边,看这两个点是否属于同一个连通分量,如果属于就舍去此边选择下一个较小的边,否则,就输出这条边,并且将这两个点合并成一个连通分量.
struct edge{int u, v, cost;};
bool comp(edge &e1, edge &e2)
{
return e1.cost < e2.cost;
}
edge es[maxe];
int V, E;
int par[manv]
void init(int n)
{
for(int i = 0; i < n; i++)
{
par[i] = i;
}
}
void unite(int x, int y)
{
par[x] = y;
}
int find(int x)
{
if(par[x] == x) return x;
return par[x] = find(par[x]);
}
bool same(int x, int y)
{
return find(x) == find(y);
}
int kruskal()
{
sort(es, es + E, comp);
init(V);
int res = 0;
for(int i = 0; i < E; i++)
{
edge e = es[i];
if(!same(e.u, e.v))
{
unit(e.u, e.v);
res += e.cost;
}
}
}