hihocoder(1098) 最小生成树Kruskal

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

 

转载于:https://www.cnblogs.com/sheepsheep/p/4419118.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值