【题目来源】
https://www.acwing.com/problem/content/4298/
【题目描述】
在某星球上生活着 n 只名为 QS 的智慧生物,编号 1∼n。
初始时,它们之间没有建立任何网络通信。
现在,它们希望全面建立通信网络,使得任意两个 QS 之间都能实现网络通信。
两个 QS 生物 A 和 B 能够实现网络通信,如果:
● A 和 B 之间存在网线直接连接。
● 存在另一只 QS 生物 C 满足 C 和 A 之间存在网线直接连接并且 C 和 B 之间能够实现网络通信。
每当两个 QS 生物想要建立网线直接连接时,所需的成本为:
● 一条网线的成本,等于两个 QS 生物之间的距离。
● 两个网络适配器(每个 QS 一个)的成本。
请注意,一个网络适配器只能在一个连接中使用。(即,如果一个 QS 想要建立四个连接,它需要购买四个适配器)。
每个 QS 都有自己喜欢的适配器并且在购买适配器时只会买该牌子的适配器。
第 i 个 QS 喜欢的适配器的单个价格为 pi。
请你计算,通过合理架设网线,使得任意两个 QS 之间都能实现网络通信的前提下,所需的总花费最少是多少。
【输入格式】
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 n。
第二行包含 n 个整数 p1,p2,…,pn。
接下来 n 行,每行包含 n 个整数,其中第 i 行第 j 列的数表示第 i 只 QS 与第 j 只 QS 之间的距离。
【输出格式】
每组数据输出一行结果,一个整数,表示最低总花费。
【数据范围】
1≤T≤10,
1≤n≤500,
1≤pi≤1000。
任意两个 QS 之间的范围 [1,1000]。
【输入样例】
1
3
10 20 30
0 100 200
100 0 300
200 300 0
【输出样例】
370
【算法分析】
本算法参考YXC大佬的经典Prim算法实现。其适用面广,不仅适用于无向连通图,也适用于无向非连通图。
即便对于边权可能为负数,且有重边和自环情形的无向连通图及无向非连通图,本算法都适用。
Prim算法模板详见:https://blog.csdn.net/hnjzsyjyj/article/details/127518589
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=505;
int g[maxn][maxn],dis[maxn],p[maxn];
bool st[maxn];
int n;
int ans;
void prim() {
memset(dis,inf,sizeof dis);
for(int i=0; i<n; i++) {
int t=-1;
for(int j=1; j<=n; j++) {
if(!st[j]&&(t==-1||dis[t]>dis[j]))
t=j;
}
st[t]=true;
if(i) ans+=dis[t];
for(int j=1; j<=n; j++) {
if(!st[j]) dis[j]=min(dis[j],g[t][j]);
}
}
cout<<ans<<endl;
}
int main() {
int T;
cin>>T;
while(T--) {
cin>>n;
memset(p,0,sizeof(p));
memset(g,0,sizeof(g));
memset(st,0,sizeof(st));
for(int i=1; i<=n; i++) cin>>p[i];
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
cin>>g[i][j];
if(i!=j) g[i][j]+=p[i]+p[j];
}
}
ans=0; //very important
prim();
}
return 0;
}
/*
in:
1
3
10 20 30
0 100 200
100 0 300
200 300 0
out:
370
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/127518589
https://www.acwing.com/solution/content/138584/