最小生成树:如果边上有权值,那么使得边权值和最小的生成树叫做最小生成树。
1.最小生成树问题1(Prim算法)
int cost[maxn][maxn]; //cost[u][v]表示边e = (u, v)的权值(不存在的情况下设为INF)
int mincost[maxn]; //从集合x出发的边到每个顶点的最小权值
bool used[maxn]; //顶点i是否包含在集合x中
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;
//从不属于x的顶点中选取从x到其权值最小的顶点
for (int u = 0; u < V; u++){
if (!used[u] && (v == -1 || mincost[u] < mincost[v]))
v = u;
}
if (v == -1)
break;
used[v] = true; //把顶点v加入x
res += mincost[v]; //把边的长度加入到结果里
for (int u = 0; u < V; u++){
mincost[u] = min(mincost[u], cost[v][u]);
}
}
return res;
}
2.最小生成树问题2(Kruskal算法)
Kruskal算法按照边的权值的顺序从小到大查看一遍,如果不产生圈(重边等也算在内),
就把当前这条边加入到生成树中。
struct edge { int u, v, cost; };
bool comp(const edge& e1, const edge& e2)
{
return e1.cost < e2.cost;
}
edge es[maxn];
int V, E; //顶点数和边数
int Kruskal()
{
sort(es, es + E, comp); //按照edge.cost的顺序从小到大排列
init_union_find(V); //并查集的初始化
int res = 0;
for (int i = 0; i < E; i++){
edge e = es[i];
if (!same(e.u, e.u)){
unite(e,u, e.v);
res += e.cost;
}
}
return res;
}