AcWing 4295:QS网络 ← Kruskal算法

【题目来源】
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算法实现。其适用面广,不仅适用于无向连通图,也适用于无向非连通图。
即便对于边权可能为负数,且有重边和自环情形的无向连通图及无向非连通图,本算法都适用。
Kruskal算法模板详见:https://blog.csdn.net/hnjzsyjyj/article/details/127524348
Prim算法模板详见:https://blog.csdn.net/hnjzsyjyj/article/details/127518589

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int maxn=505;
int p[maxn];
int T;
int n;

struct edge {
    int u,v;
    int cost;
} e[maxn*maxn]; //keypoint

bool cmp(edge x, edge y) {
    return x.cost<y.cost;
}

int pre[maxn];
int find(int x) { //DSU's find
    if(x!=pre[x]) pre[x]=find(pre[x]);
    return pre[x];
}

void Kruskal() {
    int cnt=0;
    for(int i=1; i<=n; i++) pre[i]=i; //Initialize DSU
    for(int i=1; i<=n; i++) cin>>p[i];

    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            int x;
            cin>>x;
            if(i<j) e[cnt++]= {i,j,x+p[i]+p[j]}; //i<j
        }
    }

    sort(e,e+cnt,cmp);

    int ans=0;
    for(int i=0; i<cnt; i++) {
        int fx=find(e[i].u);
        int fy=find(e[i].v);
        if(fx!=fy) {
            pre[fy]=fx;
            ans+=e[i].cost;
        }
    }
    cout<<ans<<endl;
}

int main() {
    cin>>T;
    while(T--) {
        cin>>n;
        Kruskal();
    }

    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/127524348
https://blog.csdn.net/hnjzsyjyj/article/details/139605698
https://blog.csdn.net/hnjzsyjyj/article/details/127518589
https://www.acwing.com/solution/content/190746/


 

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值