zoukankan      html  css  js  c++  java
  • 布线问题 最小生成树 prim + kruskal

    1 : 第一种 prime     首先确定一个点 作为已经确定的集合 , 然后以这个点为中心 , 向没有被收录的点 , 找最短距离( 到已经确定的点 ) , 找一个已知长度的最小长度的 边 加到 sum里面 然后收录这个点 , 

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<limits.h>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<string>
    #include<sstream>
    #include<map>
    #include<cctype>
    using namespace std;                // prim  针对点 进行 最小生成树的 构造
    int a[505][505],visited[505],tem[505],dis,minn,n,m,sum;
    int main()     //      首先  以 1 为 根节点  ,  开始向周围寻找  找到一个  最小的边
    {                   //  然后 将 该边的 另一个端点标记为  已访问  然后 将该边  的长度 加到sum 中
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            sum=0;
            for(int i=1;i<=n;i++)
            {
                tem[i]=INT_MAX;          //  除了已经确定 了的楼 , 剩余的楼 到 集合中确定的 距离都是最大
                for(int j=1;j<=n;j++)
                    a[i][j]=INT_MAX;    //    每两个楼之间的距离超大
            }
            memset(visited,0,sizeof(visited));
            while(m--)
            {
                int b,c,d;
                scanf("%d%d%d",&b,&c,&d);
                a[b][c]=a[c][b]=d;
            }
            int n1=n-1,b=0;
            b=1;  // 楼的编号 从1 开始
            visited[1]=1;  //  1号楼  已经确定
            while(n1--)   //  只需要确定  n-1  条边
            {
                minn=INT_MAX;
                for(int i=1;i<=n;i++)
                {
                    if(b!=i&&a[b][i]<tem[i]&&!visited[i])//  不是自己到自己
                    {
                        tem[i]=a[b][i];
                    }
                }
                int j;
                for(int i=1;i<=n;i++)
                {
                    if(minn>tem[i]&&!visited[i])
                    {
                        minn=tem[i];
                        j=i;            //  找到和 已知集合相连的 最小的一条边
                    }
                }
                visited[j]=1;
                b=j;
                sum+=minn;
            }
            minn=INT_MAX;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&b);
                minn=minn<b?minn:b;   // 找到   拉电源 最小花费的 楼 所花费的金额 .
            }
            printf("%d
    ",minn+sum);
        }
        return 0;
    }

    2 : kruskal     用一个结构体储存信息 , 然后 根据边长来 排序 , 然后一条一条边的收录 如果 形成了环  就不收录这一条边 .

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 #include<iostream>
     5 #include<limits.h>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<set>
    10 #include<stack>
    11 #include<string>
    12 #include<sstream>
    13 #include<map>
    14 #include<cctype>
    15 using namespace std;
    16 int father[505],sum;
    17 struct node
    18 {
    19     int x,y,l;
    20 };
    21 bool cmp(node a,node b)
    22 {
    23     return a.l<b.l;
    24 }
    25 int find(int x)                      //  做了时间上的优化 ,但是 在空间复杂度上比较高
    26 {
    27     if(x!=father[x])
    28         father[x]=find(father[x]);
    29     sum++;
    30     return father[x];
    31 }
    32 bool merge(int x,int y)    // 做了时间复杂度上的优化  让并查集的 深度尽量  浅
    33 {
    34     int sum1,sum2;
    35     sum=0;
    36     x=find(x);
    37     sum1=sum;        //    x  的深度
    38     sum=0;
    39     y=find(y);
    40     sum2=sum;       //    y   的深度
    41     if(x!=y)
    42     {
    43         if(sum1>sum2)
    44             father[y]=x;
    45         else
    46             father[x]=y;
    47         return true;
    48     }
    49     else
    50         return false;
    51 }
    52 node a[125000];
    53 int main()
    54 {
    55     int t,n,m;
    56     scanf("%d",&t);
    57     while(t--)
    58     {
    59         scanf("%d%d",&n,&m);
    60         sum=0;
    61         for(int i=0;i<m;i++)
    62         {
    63             int b,c,d;
    64             scanf("%d%d%d",&b,&c,&d);
    65             a[i].x=b;
    66             a[i].y=c;
    67             a[i].l=d;
    68         }
    69         sort(a,a+m,cmp);
    70         int count1=0;
    71         for(int i=0;i<=505;i++)
    72             father[i]=i;
    73         int sum1=0;
    74         for(int i=0;i<m;i++)    //    开始 做了他
    75         {
    76             if(merge(a[i].x,a[i].y))   //     返回 flase 的话 就代表成环了
    77             {
    78                 count1++;
    79                 sum1+=a[i].l;
    80                 if(count1==n-1)   //  如果已经形成 树的话
    81                     break;
    82             }
    83         }
    84         int minn=INT_MAX;
    85         for(int i=0;i<n;i++)
    86         {
    87             int b;
    88             scanf("%d",&b);
    89             minn=b<minn?b:minn;
    90         }
    91         printf("%d
    ",minn+sum1);
    92     }
    93     return 0;
    94 }

     

  • 相关阅读:
    Linux中增加组和用户
    Storm重启topology,失败
    ES读写数据的工作原理
    Hive优化
    Flink提交流程和架构
    Flink中的Time与Window
    linux 中文件夹的文件按照时间倒序或者升序排列
    ElasticSearch之配置文件详解
    redis中的设置bind绑定ip不是设置白名单
    YARN调度架构中的AppMaster
  • 原文地址:https://www.cnblogs.com/A-FM/p/5378798.html
Copyright © 2011-2022 走看看