本文共 2984 字,大约阅读时间需要 9 分钟。
树:同时满足极小连通图与极大无环图
支撑树:能够覆盖图中每一个顶点的树 最小支撑树:有权网络中满足各边权值之和最小的支撑树对于一幅图来说,存在的最小支撑树并不唯一。
最小支撑树总是会采用联结每一割的最短跨越边。
用我的理解,就是不断拓展树的大小,用贪心思想,在目前的最小支撑树的邻接点中搜索与树相连的边的最小权值,并将其加入树,之后更新树的邻接点的数据,直到树能够覆盖所有的顶点适用于稠密图,O(|V|^2)
#include#define MAX 0x3f3f3f;using namespace std;int sum;int n,m;//输入的N个点,和M条边int x,y,z;//输入变量int i,j,k;//循环变量int book[100];//用于记录这个点有没有被访问过int dis[100];//用于记录距离树的距离最短路程int maps[100][100];//用于记录所有边的关系int Prim(){ int min,minIndex; //初始化距离数组,默认先把离1点最近的找出来放好 for (i = 1; i <= n; i++) dis[i] = maps[1][i]; book[1]=1;//记录1已经被访问过了 for (i = 1; i <= n-1; i++){ //1已经访问过了,所以循环n-1次 min = MAX;//对于最小值赋值 for (j = 1; j <= n; j++){ //搜索树的邻接点与树相连的边的权最小值及该顶点 if(!book[j]&& dis[j] < min) { min = dis[j]; minIndex = j; } } //记录这个点已经被访问过了 book[minIndex] = 1; sum += dis[minIndex]; for (j = 1; j <= n; j++){ //刚刚树增加了一个点,现在把与这个点相连的边的数据更新为更小的权值 //通过这一步骤,我们可以在dis里面存入树的邻接点与树相连的边的权值 if(book[j] == 0 && maps[minIndex][j] < dis[j]) dis[j] = maps[minIndex][j]; } }}int main(){ cin>>n>>m;//---------------------------------------------------- //初始化maps,除了自己到自己是0其他都是边界值 for (i = 1; i <= n; i++){ for (j = 1; j <= n; j++){ if(i!=j){ maps[i][j] = MAX; } else maps[i][j] = 0; } } for (i = 1; i <= m; i++){ cin>>x>>y>>z;//输入的为无向图 maps[x][y] = z; maps[y][x] = z; }//---------------------------------------------------- cout< <
贪心思想,每次会在剩余的边中选出权值最小的边,从而构成一棵棵子树,最终合木成林,但对于边的选择却存在要求,边不能属于同一棵子树,否则就形成了环路,不符合树的要求,直至边数等于总顶点数减一,结束检索。
适用于稀疏图,O(|V|*log|V|)
#includeusing namespace std;struct Edge{ int u; int v; int w;};int parent[201];//---------------------------------------- bool cmp(Edge e1, Edge e2){ //对于结构体内部数据排序所需要 return e1.w < e2.w; }//---------------------------------------- int find(int x) { //递归求子树最终根节点 if (x == parent[x]) return x; return parent[x] = find(parent[x]);//更新每个点的最终根节点 }//---------------------------------------- int merge(int x, int y){ //判断是否属于同一棵子树 int a = find(x); int b = find(y); if (a != b) { parent[b] = a; return 1; } return 0;}int main(){ int n, e; while (cin >> n >> e){ Edge edge[e]; for (int i = 0; i >edge[i].u>>edge[i].v>>edge[i].w; } sort(edge,edge+e,cmp); int cnt = 0, sum = 0;//cnt为树中的边数,sum为树中各边之和 for (int i = 0; i < e; i++){ if (merge(edge[i].u, edge[i].v)){ cnt++; sum += edge[i].w; } if (cnt == n - 1) break; } if (cnt == n - 1) cout << sum << endl; else cout <<"NO TREE"<< endl; } return 0;}
转载地址:http://zoah.baihongyu.com/