完全图的最小生成树
关键字: 贪心算法,图,最小生成树
题目描述:给定一个图,图中包括 n 个点,每个点 i 有一个权值A[i]。这个图是一个完全图,任意两点 i 和 j 之间有一条长度为 A[i]+A[j] 的无向边,问该图最小生成树所有边的长度和。
输入:第一个数为数据组数T, T≤50。
对于每组数据,首先输入一个数n,n≤100000。
接下来一行n个数,分别表示A[1],…,A[n],1≤A[i]≤10,000,000。
输出:对于每组数据,输出一行,最小生成树的边权和。
样例:
//Input
1
4
5 6 5 9
//Output
35
题解:由于该题中边的权值由所选取的点决定,故采用prim算法构建最小生成树。由题,该树每条边的权值为该边两端点权值和,根据prim算法,选取当前点集 EEE 中最小元 uuu 为起始点,记其权值为A[uuu],不断选取当前剩余点集中的最小元 viv_ivi,记其权值为A[viv_ivi],则以点 uuu 为根,边 <u,vi><u,v_i><u,vi>为茎的树则为该完全图的最小生成树。不妨令最小元为A[vjv_jvj],则其所有边的长度和为
A[u]+A[v1]+⋯+A[u]+A[vj−1]+A[u]+A[vj+1]+⋯+A[u]+A[vn]=(n−2)A[u]+∑1nA[vi]A[u]+A[v_1]+\cdots+A[u]+A[v_{j-1}]+A[u]+A[v_{j+1}]+\cdots+A[u]+A[v_n] = (n-2)A[u]+\sum_1^nA[v_i]A[u]+A[v1]+⋯+A[u]+A[vj−1]+A[u]+A[vj+1]+⋯+A[u]+A[vn]=(n−2)A[u]+1∑nA[vi]
AC代码 (C++ 代码长度-515Bytes 运行时长-516ms 运行内存-3304KB)
#include <iostream>
#include <cstdio>
using namespace std;
int n;
void MiniSpTree ();
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
int T, t = 1;
cin >> T;
while (t <= T) {
cin >> n;
MiniSpTree ();
++t;
}
return 0;
}
void MiniSpTree () {
int min = 0x3f3f3f3f;
long long res = 0;
for (int i = 0; i < n; ++i) {
int temp;
cin >> temp;
res += temp;
if (min > temp)
min = temp;
}
res += (n-2)*min;
cout << res << endl;
}
本文介绍了一种解决完全图最小生成树问题的方法,通过贪心算法中的Prim算法来实现。具体步骤是从图中选择一个点作为起点,然后依次添加当前未加入树的节点中与树中节点连接的边权值最小的节点,直至包含所有节点。样例和AC代码也一并给出,展示了解决此类问题的完整过程。
705

被折叠的 条评论
为什么被折叠?



