最小生成树(kruskal)

Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪婪算法的应用。和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效。

时间复杂度:elog2e  e为图中的边数

原理可以参考这篇文章:

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html

实现如下:

 1 #include <iostream>
 2 #include <vector>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 vector<pair<int,int> > eg[100];
 8
 9 typedef pair<int,int> pa;
10
11 struct node
12 {
13           int x,y,w;
14
15           node(int a,int b,int c)
16           { x=a;y=b;w=c;}
17
18           bool operator <(const node &a)const
19           { return w<a.w;}
20           //为了实现sort,<是升序(小的在前),>是降序
21 };
22
23 void kruskal(int n,int d)
24 {
25           int vset[100];
26           //辅助数组,判定两个顶点是否连通
27
28           vector<node> E;
29           //保存所有边
30
31           int k,j;
32
33           //init
34           for(int i = 0;i<n;i++)
35           {
36                     vset[i] = i;
37                     for(int j = 0;j<eg[i].size();j++)
38                     {
39                               pa x = eg[i][j];
40                               E.push_back(node(i,x.first,x.second));
41                     }
42           }
43           sort(E.begin(),E.end());
44
45           k = 1;
46           //生成的边数,最后要刚好为总边数
47           int m = 0,sn1,sn2;
48           //E中的下标
49
50           while(k<n)
51           {
52                     //sn1和sn2为两个集合
53                     sn1 = vset[E[m].x];
54                     sn2 = vset[E[m].y];
55                     if(sn1!=sn2)
56                     {
57                               cout<<E[m].x<<"->"<<E[m].y<<" : "<<E[m].w<<endl;
58                               //集合的表示
59                               for(int i = 0;i<n;i++)
60                                         if(vset[i] == sn2)
61                                                   vset[i] = sn1;
62                               k++;
63                     }
64                     m++;
65           }
66
67 }
68
69
70 int main()
71 {
72           int n,d;
73           cin>>n>>d;
74           for(int i = 0;i<d;i++)
75           {
76                     int t,s,w;
77                     cin>>t>>s>>w;
78                     eg[t].push_back(make_pair(s,w));
79                     eg[s].push_back(make_pair(t,w));
80           }
81           kruskal(n,d);
82
83
84
85 }
86 /*
87 6 8
88 0 1 2
89 0 3 4
90 1 4 4
91 2 0 5
92 2 5 2
93 3 4 3
94 3 5 7
95 5 4 3
96 */
时间: 2024-10-18 15:51:59

最小生成树(kruskal)的相关文章

SOJ4339 Driving Range 最小生成树 kruskal算法

典型的最小生成树 然后求最大的一条边 附上链接 http://cstest.scu.edu.cn/soj/problem.action?id=4339 需要注意的是有可能有 "IMPOSSIBLE" 的情况 这里用一个flag标记 记录所并的节点 只有flag = n时才能成功 负责就 "IMPOSSIBLE" 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring&g

ZOJ 3204 Connect them (C) 最小生成树kruskal

Connect them Time Limit: 1 Second      Memory Limit: 32768 KB You have n computers numbered from 1 to n and you want to connect them to make a small local area network (LAN). All connections are two-way (that is connecting computers i and j is the sa

HDU2988 Dark roads 【最小生成树Kruskal】

Dark roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 583    Accepted Submission(s): 253 Problem Description Economic times these days are tough, even in Byteland. To reduce the operating

最小生成树 kruskal算法简介

生成树--在一个图中的一个联通子图  使得所有的节点都被(访问) 最小生成树 (MST) 即联通子图的总代价(路程)最小 已知的一个图 有n个点 m条边 kruskal的算法如下 先对边从小到大排序 从最小的边起,不停的合并这条边的两个节点到一个集合,如果这条边的两个节点已经在一个集合里,则无视,否则形成回路(显然错误)直到所有的节点并到一个集合里 这里需要用到并查集来合并节点 1 int cmp(const int i,const int j) { 2 return w[i] < w[j];

最小生成树 Kruskal算法

Kruskal算法 1.概览 Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表.用来解决同样问题的还有Prim算法和Boruvka算法等.三种算法都是贪婪算法的应用.和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效. 2.算法简单描述 1).记Graph中有v个顶点,e个边 2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边 3).将原图Graph中所有e个边按权值从小到大排序 4)

SDUT 2933-人活着系列之Streetlights(最小生成树Kruskal+并查集实现)

人活着系列之Streetlights Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 人活着如果是为了家庭,亲情----可以说是在这个世界上最温暖人心的,也是最让人放不下的,也是我在思索这个问题最说服自己接受的答案.对,也许活着是一种责任,为了繁殖下一代,为了孝敬父母,男人要养家糊口,女人要生儿育女,就这样循环的过下去,但最终呢?还是劳苦愁烦,转眼成空呀! 为了响应政府节约能源的政策,某市要对路灯进行改革,已知该市有n个城镇,

无向图最小生成树Kruskal算法

问题 最小生成树的Kruskal算法 描述:有A.B.C.D四个点,每两个点之间的距离(无方向)是(第一个数字是两点之间距离,后面两个字母代表两个点):(1,'A','B'),(5,'A','C'),(3,'A','D'),(4,'B','C'),(2,'B','D'),(1,'C','D') 生成边长和最小的树,也就是找出一种连接方法,将各点连接起来,并且各点之间的距离和最小. 思路说明: Kruskal算法是经典的无向图最小生成树解决方法.此处列举两种python的实现方法.这两种方法均参考

最小生成树Kruskal算法的提出者Joseph Bernard Kruskal,Jr.

熟悉算法中的最小生成树的朋友都晓得有一个Kruskal算法,这个算法就是由题目中那个名字很长的人提出的.因为他功绩卓越,尊称他为Kruskal. Kruskal生于1928年1月29日,卒于2010年9月19日,美国人,维基里的词条中包含的头衔是:数学家.统计学家.计算机科学家.心理测量学专家. kruskal分别就读过芝加哥大学和普林斯顿大学,1954年获得博士学位. 下面链接中是一篇几年他的文章,从中可以了解他的更多成就.顺便说一句,他的父母和兄弟也都很牛. http://pan.baidu

【模版】最小生成树Kruskal模版

最小生成树简单来说就是在一个有$n$条边的有权无向连通图中选出$n-1$条边,使图连通并且这$n-1$条边的边权和最小. Kruskal算法是用一种贪心的思想,先将所有的边按边权排序,按边权从小到大顺序枚举边,如果起点和终点不在一个集合,就选这条边,并将起点和终点合并成一个集合:反之则不选此边.集合可以用并查集维护. (以上内容纯属瞎编,若要系统学习请百度) 下面是模版 //最小生成树(Kruskal)模版 //By LC 2017.2.19整理 #include <cstdio> #incl

HDU3371 Connect the Cities 【最小生成树Kruskal】

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9856    Accepted Submission(s): 2800 Problem Description In 2100, since the sea level rise, most of the cities disappear. Thou