赞
踩
图分为无向图和有向图,其中包括无权,有权(正权负权)图。
定义:无向带权图G顶点个数为 m ,由G中 m 个点和 m - 1 条边构成的连通子图称为G的一条支撑树,也叫生成树。 边权之和最小的支撑树叫做最小支撑树(MST)。
最小支撑树无回路
Prim算法更适用于稠密图(点少边多)。
过程图解
利用并查集实现,将每个连通分量看作一个集合,顶点看作集合元素,每次查询一条权值最小的边,查询该边的两端是否在同一个集合内,若不在就将这两个集合合并,将该边加入支撑树中。Kruskal算法更适用于稀疏图(点多边少)。
过程图解
-
- #include<iostream>
- using namespace std;
- #define WQ 65535//有符号的最大值表示无穷大
-
- int edge[2000][2000];//邻接矩阵
- long long sum;//权值之和
- int TE[1000];
- int lowcost[2000];//最小权值数组
- int U[2000];
- bool flag = false;
- //构建邻接矩阵
- void CreatGraph(int n, int e) {
-
- for (int i = 1; i <= n; i++) {
- for (int j = 1; j <= n; j++) {
- edge[i][j] = WQ;
- }
- }
- for (int k = 0; k < e; k++) {
- int a, b, c;
- cin >> a >> b >> c;
- edge[a][b] = c;
- edge[b][a] = edge[a][b];
- }
- }
- void Prim(int n, int e) {
- flag = false;
- for (int i = 1; i <= n; i++) {
- lowcost[i] = edge[1][i];
- U[i] = 1;
- }
- U[1] = -1;
- int k = 1;
- for (int i = 1; i <= n - 1; i++) {
- int v = 0;
- int min = WQ;//无穷大
- for (int j = 1; j <= n; j++) {
- if (U[j] != -1 && lowcost[j] < min) {//初始化
- v = j;
- min = lowcost[j];
- }
- }
- if (v == 0) {
- flag = true;
- printf("There is no minimum spanning tree.\n");
- return;
- //图不连通
- }
- TE[k] = lowcost[v];
- k = k + 1;
- lowcost[v] = 0;
- U[v] = -1;
- for (int j = 1; j <= n; j++) {
- if (U[j] != -1 && edge[v][j] < lowcost[j]) {//更新权值
- lowcost[j] = edge[v][j];
- U[j] = v;
- }
- }
- }
-
- //return 0;
- }
-
- //主函数
- int main() {
- int n;//顶点数
- int e;//边数
- while (scanf("%d%d", &n, &e) != EOF)
- {
- CreatGraph(n, e);//构建邻接矩阵
- Prim(n, e);
- if (flag == false) {
- for (int i = 1; i <= e; i++) {
- sum += TE[i];
- }
- cout << sum << endl;
- }
- }
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。