最小生成树
Posted 会宁狐狸
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树相关的知识,希望对你有一定的参考价值。
INTRODUCTION
一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。
--百度百科
概述
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得
的 w(T) 最小,则此 T 为 G 的最小生成树。
最小生成树其实是最小权重生成树的简称。
--百度百科
最小生成树的性质:
最小生成树性质:设G=(V,E)是一个连通网络,U是顶点集V的一个非空真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。--百度百科
通俗来说
对于一个连通图,若已经求出最小生成树A,则若能找出最小生成树B与A不同
则这个图中,至少有两条边边权相等,且两条边在同一个环上,删去这两条边中的任意一条不影响原图的连通性,
且在生成树A,B中等边权的边的数量相等
推论
对于一个连通图,将他制成一颗生成树,使他的最大边最小,则这棵树是该图的最小生成树
不存在比最小生成树中最大边i更小的边j,当j将i替换后原图联通,若替换后仍联通,则j的权值必定比i大
因为在求最小生成树时已经保证最小联通
最小生成树的求法:
1,Kruskal
大致思路在于将每一条边按照边权从小到大排序,之后按这个顺序扫一遍,若这条边的起点和终点尚未联通或间接联通,那加上这条边,把这两个点连起来,那么怎么判断联通呢?自然要靠并查集了
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 int f[100086]; 7 struct edge 8 { 9 int from; 10 int to; 11 int weight; 12 }; 13 int n, m; 14 int tot; 15 long long ans; 16 vector<edge>e; 17 int find(int x)//普通的并查集 18 { 19 if (f[x] == x) 20 return x; 21 else 22 return f[x] = find(f[x]); 23 } 24 void merge(int a, int b) 25 { 26 int x = find(a); 27 int y = find(b); 28 if (f[x] != f[y]) 29 f[y] = x; 30 } 31 bool cmp(edge a, edge b) 32 { 33 return a.weight < b.weight; 34 } 35 int main() 36 { 37 cin >> n >> m; 38 for (int i = 1; i <= n; i++) 39 f[i] = i;//并查集初始化 40 for (int i = 1; i <= m; i++) 41 { 42 int x, y, z; 43 cin >> x >> y >> z; 44 edge t; 45 t.from = x; 46 t.to = y; 47 t.weight = z; 48 e.push_back(t); 49 t.from = y; 50 t.to = x; 51 e.push_back(t); 52 } 53 sort(e.begin(), e.end(), cmp); 54 for (int i = 0; i < e.size(); i++) 55 { 56 if (find(e[i].from) != find(e[i].to)) 57 { 58 merge(e[i].from, e[i].to); 59 ans += e[i].weight; 60 } 61 } 62 cout << ans << endl; 63 return 0; 64 }
2,Prim
以上是关于最小生成树的主要内容,如果未能解决你的问题,请参考以下文章