欢迎来到PJCK的博客

(最小生成树) codeVs 1231 最优布线问题

题目描述 Description

学校需要将n台计算机连接起来,不同的2台计算机之间的连接费用可能是不同的。为了节省费用,我们考虑采用间接数据传输结束,就是一台计算机可以间接地通过其他计算机实现和另外一台计算机连接。

为了使得任意两台计算机之间都是连通的(不管是直接还是间接的),需要在若干台计算机之间用网线直接连接,现在想使得总的连接费用最省,让你编程计算这个最小的费用。

输入描述 Input Description

输入第一行为两个整数n,m(2<=n<=100000,2<=m<=100000),表示计算机总数,和可以互相建立连接的连接个数。接下来m行,每行三个整数a,b,c 表示在机器a和机器b之间建立连接的话费是c。(题目保证一定存在可行的连通方案, 数据中可能存在权值不一样的重边,但是保证没有自环)

输出描述 Output Description

输出只有一行一个整数,表示最省的总连接费用。

样例输入 Sample Input

3 3

1 2 1

1 3 2

2 3 1

样例输出 Sample Output

2

------------------------------------------------------------------------------------------------------------------------------------------------------------------

计算机总数最大为100000,所以用Prim算法时建立二维数组会越界,而用常规Kruskal算法会超时,所以用并查集优化的Kruskal算法。

C++代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100003;
struct Edge{
    int a;
    int b;
    int c;
}e[N];
bool cmp(Edge a,Edge b){
    return a.c < b.c;
}
int n,m;
int father[N];
void Init(int n){
    for(int i = 1; i <= n; i++)
        father[i] = i;
} 
int Find(int x){
    if(x != father[x])
        father[x] = Find(father[x]);
    return father[x];
}
int Merge(int a,int b){
    int p = Find(a);
    int q = Find(b);
    if(p == q)     return 0;
//    if(p > q)
//        father[p] = q;
//    else
//        father[q] = p;
    father[p] = q;  //可以不用比较哪个父节点的值更大,直接把其中一个并到另一个下面就行。 
    return 1;
}
long long Kruskal(int n,int m){
    long long ans = 0;
    for(int i = 1; i <= m; i++){
        if(Merge(e[i].a,e[i].b)){
            ans+=e[i].c;
            n--;
            if(n==1)
                return ans;
        }
    }
    return 0;
}
int main(){
    cin>>n>>m;
    Init(n);
    for(int i = 1; i <= m; i++){
        cin>>e[i].a>>e[i].b>>e[i].c;
    }
    sort(e+1,e+m+1,cmp);
    long long ans = Kruskal(n,m);
    cout<<ans<<endl;
    return 0;
}

 

 

posted @ 2019-04-03 17:19  PJCK  阅读(246)  评论(0编辑  收藏  举报