kruskal 最小生成树算法

Posted lqsukida

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kruskal 最小生成树算法相关的知识,希望对你有一定的参考价值。

今天在vjudge上做了这题,非常水的一道板子题,一眼就能看出来是个最小生成树

然后就用prim随便做了下

结果就超时了TT

但是我不会kruskal啊,没办法,就随便看了下这个算法的思想,发现还挺好理解的?就是个贪心+并查集

于是又一次自信满满地码完之后一交

又双叒超时了TT

最后错了两三次之后不得已跑到csdn上看了下这个模板……发现自己还是认识得浅薄了点儿,所以不够快TT

下面直接放代码,然后理解的话先标下方等以后有时间了做成注释

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5  
 6 const int N = 105, M = 10050;
 7 int par[N], ans, n, m, t;
 8 struct edge { int u, v, w;} e[M];
 9 bool cmp(edge a, edge b){ return a.w < b.w;}
10  
11 long long read()
12 {
13     char ch=getchar();
14     long long x=0;
15     while(ch>9 || ch<0)ch=getchar();
16     while(ch>=0 && ch<=9)x=(x<<1)+(x<<3)+(ch^0),ch=getchar();
17     return x;
18 }
19 
20 int find(int x)
21 {
22     int r = x, tmp;
23     while(par[r] >= 0) r = par[r];
24     while(x != r)
25     {
26         tmp = par[x];
27         par[x] = r;
28         x = tmp;
29     }
30     return r;
31 }
32  
33 void unio(int u, int v)
34 {
35     int ru = find(u), rv = find(v), tmp = par[ru] + par[rv];
36     if(par[ru] < par[rv])
37         par[rv] = ru, par[ru] = tmp;
38     else
39         par[ru] = rv, par[rv] = tmp;
40 }
41  
42 void kruskal()
43 {
44     int cur = 0, u, v;
45     memset(par, -1, sizeof(par));
46     for(int i = 1; i <= m; ++i)
47     {
48         u = e[i].u, v = e[i].v;
49         if(find(u) != find(v))
50         {
51             ans += e[i].w;
52             unio(u, v);
53             ++cur;
54         }
55         if(cur >= n - 1) return;
56     }
57 }
58  
59 int main()
60 {
61     while(~scanf("%d", &n))
62     {
63         ans = m = 0;
64         for(int i = 1; i <= n; ++i)
65         {
66             for(int j = 1; j <= n; ++j)
67             {
68                 t=read();
69                 if(j < i) e[++m].u = i, e[m].v = j, e[m].w = t;
70             }
71         }
72         sort(e + 1, e + m + 1, cmp);
73         kruskal();
74         printf("%d
", ans);
75     }
76     return 0;
77 }
View Code

来下面解释下之前花了一阵子才理解的玩意儿TT

大部分还是很好理解的嘛,就排个序然后贪心选最短嘛,但是可能会成环,怎么办呢?当当当并查集!over!

以上都是幼儿园知识(dbq太自大了xxx我之前做的时候没有注意到略过了的才是重头戏

好的那就直接来介绍重头戏的两个函数——find&union

是的这两个函数是并查集非常经典的两个函数,但是在这里的话有了改进,具体分析见下

  • 首先在kruskal函数首对fa赋初值,全部为-1(这就是第一个不一样的地方
  • 接下来在find函数中 如果它爹<0,显然它还没爹,不用再找,这儿是一样的

            然后如果它爹>=0,就说明它有爹了,那么它这里是用的while循环……学不来学不来xxx虽然并不太喜欢while实现的并查集但没办法,含泪学下while实现的并查集就为了不超时(哇突然感觉自己付出好多 突然戏精

  • 然后进入union←这里还挺神仙代码的我觉得……还是没有很懂

            这样的:……我日我感觉我好想还是没懂……我真是太傻了……dbq我再研究下明白了再写TT我真的好弱啊……好烦TT

 


以上是关于kruskal 最小生成树算法的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树详解 prim+ kruskal代码模板

(最小生成树)Kruskal算法

最小生成树及Prim算法及Kruskal算法的代码实现

最小生成树算法:Kruskal算法 Prim算法

最小生成树

图解:如何实现最小生成树(Prim算法与Kruskal算法)