<学习笔记> 最小生成树 Kruskal

先来看看一般的问题:给你n个点,m条边,每条边都有一个边权,问你保留哪些边才能使n个点都互相连通同时边权和最小,求最小边权和。

不难想到只要要建一棵树(n-1条边),同时保证边权和最小。

kruskal算法:利用贪心的思想,把边按照边权从小到大排序,每次对于当前边,检查终点和起点是否连通,若不连通就加边,直到加到n-1条边为止。

最小生成树性质:任意两点之间的最短路径一定在最小生成树中,可以用反证法。

代码:codevs 1078 最小生成树

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 int N,cnt,k,Cnt,ans;
 9 int fa[110];
10 
11 struct maple{
12     int f,t,d;
13 }Rode[1000010]; 
14 
15 void Build(int f,int t,int d)
16 {
17     Rode[++cnt]=(maple){f,t,d};
18 }
19 int find(int x)
20 {
21     return fa[x]==x?x:fa[x]=find(fa[x]);
22 }
23 bool cmp(maple a,maple b)
24 {
25     return a.d<b.d;
26 }
27 
28 int main()
29 {
30     scanf("%d",&N);
31     for(int i=1;i<=N;++i)  fa[i]=i;
32     for(int i=1;i<=N;++i)
33        for(int j=1;j<=N;++j)
34        {
35               scanf("%d",&k);
36               if(i<j) Build(i,j,k);
37        }
38     sort(Rode+1,Rode+cnt+1,cmp);
39     for(int i=1;i<=cnt;++i)
40     {
41         int x=find(Rode[i].f),y=find(Rode[i].t);
42         if(x!=y)
43         {
44             ans+=Rode[i].d;
45             fa[x]=y;
46             ++Cnt;
47             if(Cnt==N-1) break;
48         }
49     }
50     printf("%d",ans);
51     return 0;
52 }
原文地址:https://www.cnblogs.com/maple-kingdom/p/maple-kingdom_tree.html