• 最小生成数之Kruskal算法


    描述

    随着小Hi拥有城市数目的增加,在之间所使用的Prim算法已经无法继续使用了——但是幸运的是,经过计算机的分析,小Hi已经筛选出了一些比较适合建造道路的路线,这个数量并没有特别的大。

    所以问题变成了——小Hi现在手上拥有N座城市,且已知其中一些城市间建造道路的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A、B、C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两条道路连通的)。

    输入

    每个测试点(输入文件)有且仅有一组测试数据。

    在一组测试数据中:

    第1行为2个整数N、M,表示小Hi拥有的城市数量和小Hi筛选出路线的条数。

    接下来的M行,每行描述一条路线,其中第i行为3个整数N1_i, N2_i, V_i,分别表示这条路线的两个端点和在这条路线上建造道路的费用。

    对于100%的数据,满足N<=10^5, M<=10^6,于任意i满足1<=N1_i, N2_i<=N, N1_i≠N2_i, 1<=V_i<=10^3.

    对于100%的数据,满足一定存在一种方案,使得任意两座城市都可以互相到达。

    输出

    对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。

    Sample Input

    5 29
    1 2 674
    2 3 249
    3 4 672
    4 5 933
    1 2 788
    3 4 147
    2 4 504
    3 4 38
    1 3 65
    3 5 6
    1 5 865
    1 3 590
    1 4 682
    2 4 227
    2 4 636
    1 4 312
    1 3 143
    2 5 158
    2 3 516
    3 5 102
    1 5 605
    1 4 99
    4 5 224
    2 4 198
    3 5 894
    1 5 845
    3 4 7
    2 4 14
    1 4 185

    Sample Output

    92
    题意描述:
    输入城市的个数以及道路的条数
    计算并输出将这些城市连通的最短距离
    解题思路:
    典型的最小生成树问题,根据数据的格式,使用Kruskal算法即可。Kruskal算法的主要思路是将所有的边都用结构体数组存起来,对其进行从小到大排序,再遍历每一条边,每次选出最短的那一条边,另外,
    如果选择的最短边加入到生成树中后会构成回路的话,则需要弃用该条边,选择次短边,重复选边,直到选择了n-1条边。
    判断加入这条边是否会构成回路,使用了并查集的算法。
    代码实现:
     1 #include<stdio.h>
     2 #include<string.h>
     3 struct edge
     4 {
     5     int u,v,w;
     6 };
     7 struct edge e[1000010];
     8 #include<algorithm>
     9 using namespace std;
    10 bool cmp(struct edge x,struct edge y)
    11 {
    12     return x.w<y.w;
    13 }
    14 int f[100010];
    15 int merge(int v,int u);
    16 int getf(int v);
    17 int main()
    18 {
    19     int n,m,i,sum,c;
    20     while(scanf("%d%d",&n,&m) != EOF)
    21     {
    22         for(i=1;i<=m;i++)
    23             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    24         sort(e+1,e+m+1,cmp);
    25         for(i=1;i<=n;i++)
    26             f[i]=i;
    27         sum=0;
    28         c=0;
    29         for(i=1;i<=m;i++)
    30         {
    31             if( merge(e[i].u,e[i].v) )//判断是否能够构成回路 
    32             {
    33                 c++;
    34                 sum += e[i].w;
    35             }
    36             if(c==n-1)
    37                 break;
    38         }
    39         printf("%d
    ",sum);
    40     }
    41     return 0;
    42  } 
    43 int getf(int v)
    44 {
    45     if(f[v]==v)//键盘功力 
    46     return v;
    47     else
    48     {
    49         f[v]=getf(f[v]);
    50         return f[v];
    51     }
    52 }
    53 int merge(int v,int u)
    54 {
    55     int t1,t2;
    56     t1=getf(v);
    57     t2=getf(u);
    58     if(t1 != t2)
    59     {
    60         f[t2]=t1;//收录 
    61         return 1;//不构成回路,返回1表示可以建造这条路 
    62     }
    63     return 0;//返回0表示已经构成了回路,不能建造这条路 
    64 }
  • 相关阅读:
    php算法之选择排序
    php算法之插入排序
    五分钟读懂UML类图
    ZC_知识点
    JNI_C#
    JNI_Z
    20160419__第1课_第6课
    Hibernate异常_01
    ZC_注意点
    ZC_知识点
  • 原文地址:https://www.cnblogs.com/wenzhixin/p/7277791.html
Copyright © 2020-2023  润新知