【图论】最小生成树
最小生成树概念:
给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一颗树,那么这棵树就称为生成树。如果边上有权值,那么使得边权和最小的生成树就叫做最小生成树(MST)。
常用算法:Prim 算法, Kruskal算法
Prim 算法
Prim算法与Dijkstra算法十分相似,基于贪心思想。
模板:
const int INF = 0x3f3f3f3f;
int cost[MAX_V][MAX_V];
int mincost[MAX_V];
bool used[MAX_V];
int V;
int prim(){
for(int i = 0; i < V; ++i){
mincost[i] = INF;
used[i] = false;
}
mincost[0] = 0;
used[0] = true;
int res = 0;
for(int i = 1; i < V; ++i){
int v = -1;
for(int j = 0; j < V; ++j){
if(!used[j] && (v == -1 || mincost[j] < mincost[v]))
v = j;
}
if(v == -1) return -1; // 图不连通
used[v] = true;
res += mincost[v];
for(int j = 0; j < V; ++j){
if(!used[j] && mincost[j] > cost[v][j])
mincost[j] = cost[v][j];
}
}
return res;
}
Kruskal 算法
模板:
const int INF = 0x3f3f3f3f;
struct Edge{
int u, v, cost;
};
bool comp(const Edge& e1, const Edge& e2){
return e1.cost < e2.cost;
}
Edge edge[MAX_E];
int f[MAX_V];// 并查集
int V, E;
int Find(int x){
if(f[x] == - 1)
return x;
return f[x] = Find(f[x]);
}
int kruskal(){
for(int i = 0; i < MAX_V; ++i){
f[i] = -1;
}
sort(edge, edge + E, comp);
int res = 0, cnt = 0;
for(int i = 0; i < E; ++i){
Edge e = es[i];
int t1 = Find(e.u);
int t2 = Find(e,v);
if(t1 != t2){
res += e.cost;
f[t1] = t2;
++cnt;
}
if(cnt == n - 1) break;
}
if(cnt < n - 1) return -1; // 不连通
else return res;
}

浙公网安备 33010602011771号