码迷,mamicode.com
首页 > 其他好文 > 详细

hihocoder(1098) 最小生成树Kruskal

时间:2015-04-12 10:38:31      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:

Kruskal比Prim简单的多,对已知边排序,然后从排序的边中跳出N-1条最短的来就可以了,当然,如果在挑的过程中出现环,就丢掉继续找,就只这么直接。

如何判定有没有环?很简单,用并查集就可以。

比如a-b,b-c,c-a构成了环,那么a-b合并,b-c合并后,如果紧接着最小边是c-a,那么并查集的find(c,a)操作就会告诉你,c,a是同一个环内,跳过,继续。

总结一下:

(1)对已知边排序(如果用数组存顶点,那么直接用qsort()就行了,如果用vector,那么sort()就行了)

(2)从已排序的边中找出一条最小边,如果该边与当前最小生成树形成环,跳过,否则合并端点e.a,e.b,将当前边加入最小生成树内。

(3)循环。

由于挑选的过程是一个O(e)的过程,那么其实Kurskal的时间复杂度主要由其排序时间决定,O(eloge)。这也是Kruskal非常适合稀疏图的原因。

技术分享
 1 struct Edge
 2 {
 3     int a;
 4     int b;
 5     int weight;
 6 };
 7 
 8 int edgeCmp(const void* ea, const void* eb)
 9 {
10     return reinterpret_cast<const Edge*>(ea)->weight - reinterpret_cast<const Edge*>(eb)->weight;
11 }
12 
13 int N, M;
14 int p[100010];
15 Edge e[1000010];
16 
17 int find(int i) 
18 {
19     if (p[i] == i)
20         return i;
21     return p[i] = find(p[i]);
22 }
23 
24 void merge(int i, int j)
25 {
26     if (find(i) != find(j))
27         p[find(i)] = find(j);
28 }
29 
30 int kruskal() 
31 {
32     int res=0;
33     qsort(e, M, sizeof(Edge), edgeCmp);
34     for (int i = 0; i < M; ++i) 
35     {
36         if (find(e[i].a) == find(e[i].b))
37             continue;
38         res += e[i].weight;
39         merge(e[i].a, e[i].b);
40     }
41 
42     return res;
43 }
44 
45 int main()
46 {
47     scanf("%d%d", &N, &M);
48     for (int i = 1; i <= N; ++i) p[i] = i;
49     for (int i = 0; i < M; ++i)
50         scanf("%d%d%d", &(e[i].a), &(e[i].b), &(e[i].weight));
51 
52     printf("%d\n", kruskal());
53 
54     return 0;
55 }
View Code

 

hihocoder(1098) 最小生成树Kruskal

标签:

原文地址:http://www.cnblogs.com/sheepsheep/p/4419118.html

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