反向删除算法合并最小生成树

1.反向删除算法

G<V,E>是连通图,删除环(如果有)上权最大边得G2,存在最小生成树属于G2

证明:假定最小生成树存在此边e,删除e,出现两个连通分支,必然环上有另一边横跨连通分支,且不属于此生成树(否则成环),连接该边,得新的最小生成树,不包含e,所以属于G2.

&&&(其实若权最大边严格大于其他边,那么最小树一定不包含他)

已经有两颗最小生成树(森林),如何用反向生成合并他们呢(红色是未选择的边)

如果两棵生成树由反向生成算法产生,那么下面可以视为中间过程,继续实施反向删除算法即可得到最小生成树,(可是生成树可以由其他方式生成,prim,kruskal,所以现在证明任一棵最小生成树可通过反向删除产生)

因为黑边权<=红边权(由&&&得),红边是最大权边,施行反向删除得最小生成树

现在可以回答这个问题了,假如已经有最小生成树构成的森林,对于其中两棵最小生成树,我们只要连接他们之间的边,再进行反向删除,这样两两合并,形成最后的最小生成树。

也可以把所有树之间的边连接起来,再实施反向删除。

 相关信息参见《算法设计》p91

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最小生成问题是图论中的经典问题之一,可以使用贪心算法求解。下面是基于Prim算法的C++代码实现: ```c++ #include <iostream> #include <vector> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; // 无穷大 const int MAXN = 10005; // 最大顶点数 struct Edge { int to; int weight; Edge(int t, int w) : to(t), weight(w) {} }; vector<Edge> graph[MAXN]; // 图的邻接表存储 int dis[MAXN]; // 存储已选中的点到未选中的点的最小距离 bool vis[MAXN]; // 记录是否已选中 int prim(int s, int n) { memset(vis, false, sizeof(vis)); memset(dis, INF, sizeof(dis)); dis[s] = 0; priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq; pq.push(make_pair(0, s)); int ans = 0; while (!pq.empty()) { int u = pq.top().second; pq.pop(); if (vis[u]) continue; vis[u] = true; ans += dis[u]; for (int i = 0; i < graph[u].size(); ++i) { int v = graph[u][i].to; int w = graph[u][i].weight; if (!vis[v] && w < dis[v]) { dis[v] = w; pq.push(make_pair(dis[v], v)); } } } return ans; } int main() { int n, m; // n为顶点数,m为边数 cin >> n >> m; for (int i = 0; i < m; ++i) { int u, v, w; // u, v为边的两个顶点,w为边的权值 cin >> u >> v >> w; graph[u].push_back(Edge(v, w)); graph[v].push_back(Edge(u, w)); // 无向图需要将边反向加入邻接表 } int ans = prim(1, n); // 从顶点1开始 cout << ans << endl; return 0; } ``` 该代码使用了邻接表存储图,利用priority_queue实现了Prim算法。其中dis数组存储已选中的点到未选中的点的最小距离,vis数组记录是否已选中。在每次从优先队列中取出一个点u时,遍历u的所有邻边v,如果v未被选中且u到v的距离小于dis[v],则更新dis[v]并将v加入优先队列。最终答案为dis数组中所有非无穷大元素之和。 需要注意的是,该代码假设图是联通的。如果图不是联通的,需要对每个连通块分别执行Prim算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值