最小生成树
kruskal prim ..
kruskal
- 思路 贪心,每次选择权值最小的边,保证每次加入新边不会生成环
- 难点 如何判定生成环,方法:保证新加入的边的两个端点,不都在已加入的边的端点集合中,用并查集实现
- 链式前向星模板 时间O(m*logm)(m为边数)
1 | //链式前向星(kruskal用邻接矩阵不太好写)----------------------------------- |
灵活运用,唯一最小生成树(思维)
题目链接 https://vjudge.net/problem/POJ-1679
题意 判断最小生成树是否唯一
思路枚举最小生成树的n条边,每次减去一条边,看最小生成树是否存在
弱思维
题面:求两个树的笛卡尔积产生的树的最小生成树。
如图:
思路:这个画个图,模拟一下应该不难想
1 | /* |
prim
- 思路 感觉本质上就是kruskal,与kruskal思路没啥区别,要说区别就是kruskal过程上是加边,这个是过程上加点吧,但其实都是每次选择权值最小的边,都是贪心。
- 具体方法 弄两个点集,一个u,一个v,每次选择一个端点在u,一个端点在v产生的边中,权值最小的边,并把在v中的点,加入u中。
- 链式前向星模板 时间O(n*n)
1 | //链式前向星----------------------------------------------------------------------------- |
- 邻接矩阵模板 时间O(n*n)
1 | //邻接矩阵----------------------------------------------------------------------------- |
灵活运用(已建立某些边)
继续畅通工程
题意 在有些边已经建立好了的情况下,求最小生成树。
思路 对于已经建立的边,将其权值变为0即可。
灵活运用(已知每个点的代价)
Shichikuji and Power Grid
常见最小生成树是知道每条边的代价,这题增加了一个就是还知道每个点的代价。
题面
有n个城市,坐标为(xi,yi),还有两个系数ci,ki.在每个城市建立发电站需要费用ci.如果不建立发电站,要让城市通电,就需要与有发电站的城市连通。i与j之间连一条无向的边的费用是(ki+kj)*两个城市之间的曼哈顿距离.求让每个城市都通电的最小费用,并输出任意一个方案。
分析
我刚开始想的就是,这不就是prim,然后将dis[i]初始化为每个点的代价嘛,然后发现这是个常见套路,也可以把选每个点的代价转成虚拟原点到这个点的边,不过这样子更好理解。这个套路很常见,但在最小生成树题里还是第一次见到。
城市之间两两连边,边权按题目里提到的计算。然后建立一个虚拟源点,向每个城市i连边,边权为ci.对整个图跑一个最小生成树即可.
总结
两者区别这个方法的好处就是,因为分成了两个点集合,所以保证了选择的权值最小的边肯定不会产生环,因为这个边的端点分别在两个互斥的集合嘛,不像kruskal选择的边可能都在集合u。
稀疏图与稠密图数据结构中对于稀疏图的定义为:有很少条边或弧(边的条数|E|远小于|V|²)的图称为稀疏图(sparse graph),反之边的条数|E|接近|V|²,称为稠密图(dense graph)。此定义来自百度百科,实际上是一种朴素的理解,简单来说边越多,图就越稠密
两者复杂度
Kruskal:
Prim: