zoukankan      html  css  js  c++  java
  • 19.最优布线问题(kruskal算法)

    最优布线问题(kruskal算法)

    时间限制: 1 s

     空间限制: 128000 KB

     题目等级 : 白银 Silver

    题解

     查看运行结果

    题目描述 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

    代码:

    #include

    using namespace std;

    #include

    #include

    #include

    #define maxn 100001

    #define INF 0x7fffffff

    int n,m,a,b,c;

    long long tot=0;//long long 才能存下

    int father[maxn]={0};

    struct Edge{

           int u,v,w,next;

    };

    Edge edge[maxn];

    void input();

    void krsual();

    int main()

    {

           input();

           krsual();

           printf("%lld ",tot);

           return 0;

    }

    int cmp(const Edge &a,const Edge &b)

    {

           return a.w

    }

    void input()

    {

           scanf("%d%d",&n,&m);

           for(int i=1;i<=m;++i)

           edge[i].w=INF;

           for(int i=1;i<=m;++i)

           {

                  scanf("%d%d%d",&a,&b,&c);

                  if(edge[i].w>c)

                  {

                         edge[i].w=c;

                         edge[i].u=a;

                         edge[i].v=b;

                  //     edge[i+m].w=c;(处理无向图的边表,都加m就可以了)

                  //     edge[i+m].v=a;

                  //     edge[i+m].u=b;

                  }

           }

    }

    int find(int x)

    {

           if(father[x]!=x) father[x]=find(father[x]);

           return father[x];

    }

    void unionn(int r1,int r2)

    {

           father[r2]=r1;

    }

    int k=0;

    void krsual()

    {

                  for(int i=1;i<=n;++i)

                father[i]=i;

               sort(edge+1,edge+m+1,cmp);

               for(int i=1;i<=m;++i)//把所有的边都遍历一遍

               {

                      int r1=find(edge[i].u);

                      int r2=find(edge[i].v);

                      if(r1!=r2)//注意并查集合并和查找都是找的集合的代表元素

                      {

                             unionn(r1,r2);//不是合并两个点,是合并代表元素

                             tot+=edge[i].w;

                             k++;

                             if(k==n-1) return ;//计数,n-1条边就够了

                            

                         }

                  }

    }

  • 相关阅读:
    bzoj3380+3381+3382+3383 Usaco2004 Open
    浅谈树链剖分(C++、算法、树结构)
    小学奥数 最大公约数与最小公倍数
    小学奥数 质数的和与积
    小学奥数 分苹果
    小学奥数 连乘积末尾0的个数
    小学奥数 李白的酒
    小学奥数 回文数个数
    小学奥数 等差数列末项计算
    小学奥数 地球人口承载力估计
  • 原文地址:https://www.cnblogs.com/csgc0131123/p/5290300.html
Copyright © 2011-2022 走看看