码迷,mamicode.com
首页 > 编程语言 > 详细

kruskal 最小生成树算法

时间:2018-10-07 23:19:26      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:pre   can   技术   span   循环   scanf   介绍   str   函数   

今天在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\n", 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 最小生成树算法

标签:pre   can   技术   span   循环   scanf   介绍   str   函数   

原文地址:https://www.cnblogs.com/lqsukida/p/9751785.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!