最小生成树

最小生成树问题,可以用克鲁斯卡尔算法和普利姆算法,Prim最主要的思想是根据顶点来得出结果,而Kruscal则是根据边来得出结果的,因此Prim最要运用于稠密图的计算,而Kruskal主要是运用于稀疏图的计算。因为只能选择一个楼连接到外界供电设备,所以只要构成最小生成树的边的和加上与外界连接花费最小的值就可以。

Kruskal:算法第一步是给所有边按从小到大排序

                         第二步初始化最小生成树为空,(初始化连通分量,每个点自成一个独立的连通分量,所以初始状态有多少顶点就有多少连通分量)

                         第三步按照排列好的顺序,如果两条边不在同一个连通分量,将这两条边合并为同一个连通分量;如果两条边在同一个连通分量里,那么如果再进行连通处理会形成环,所以不能选择。

                        第四步最小生成树的边的个数是顶点个数减一,可以通过这个来判断生成树是否正确。

传送门:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 struct node {
 7     int x,y;
 8     int w;
 9 };
10 node s[250000];
11 int f[510];//表示各个顶点在不同的分量(即所属父亲)
12 int sum;//记录最小的花费
13 int v,e,n;
14 int ss[510];//楼的花费
15 
16 int cmp(node a,node b)
17 {
18     return a.w<b.w;
19 }
20 void kruscal()//kruscal 入口 
21 {
22     int q;   
23     for(int i=0;i<=v;i++)
24         f[i]=i;
25     sort(s,s+e,cmp);
26     int num=1,j;  //记录边的个数 
27     int k=0;//循环边的下标 
28     while(num<v)
29     {
30         if(f[s[k].x]!=f[s[k].y]) //判断这条边是否构成回路 
31         {
32             num++;
33             sum+=s[k].w;
34             q=f[s[k].y];
35             for(j=1;j<=v;j++)//循环每个和q相等的顶点父亲 .
36             {
37                 if(f[j]==q)    f[j]=f[s[k].x];
38             }
39         }
40         k++;//循环每条边 
41     }
42 }        
43 int main()
44 {
45     scanf("%d",&n);
46     while(n--)
47     {
48         sum=0;
49         scanf("%d%d",&v,&e);
50         for(int i=0;i<e;i++)
51             scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].w);
52         for(int i=0;i<v;i++)
53             scanf("%d",ss+i);
54         sort(ss,ss+v);
55         kruscal();
56         printf("%d
",sum+ss[0]);
57     }
58     return 0;
59 }
60 
61         
krusckal
 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 int sum;
 6 bool vis[510];//标志是否添加到生成点
 7 int map[501][501];
 8 int des[510]; //生成的点到未生成的点距离
 9 
10 void init(int v)
11 {
12     int i,j;
13     for(i=0;i<=v;i++)
14     {
15         for(j=0;j<=v;j++)
16             map[i][j]=99999999;
17     }
18 }
19 
20 void prim(int v,int e)
21 {
22     int i,j;
23     memset(vis,0,sizeof(vis));
24     for(i=1;i<=v;i++)
25         des[i]=map[1][i];
26     vis[1]=1;
27     des[1]=0;
28     int num=1;
29     while(num<v)
30     {
31         int min=99999999,k;
32         for(i=2;i<=v;i++)
33         {
34             if(des[i]<min&&vis[i]==0)
35             {
36                 min=des[i];
37                 k=i;
38             }
39         }
40             sum+=min;
41             vis[k]=1;
42             num++;
43             for(i=2;i<=v;i++)
44             {
45                 if(map[k][i]<des[i]&&vis[i]==0)
46                     des[i]=map[k][i];
47             }
48     }
49 }
50 int main()
51 {
52     int n,v,e;
53     scanf("%d",&n);
54     while(n--)
55     {
56         sum=0;
57         scanf("%d%d",&v,&e);
58         init(v);
59         int i,a,b,c;
60         for(i=0;i<e;i++)
61         {
62             scanf("%d%d%d",&a,&b,&c);
63             if(map[a][b]>c)
64                 map[a][b]=map[b][a]=c;
65         }
66         int t=99999999;
67         for(i=0;i<v;i++)
68         {
69             scanf("%d",&a);
70             if(t>a)
71                 t=a;
72         }
73         prim(v,e);
74         printf("%d
",sum+t);
75     }
76     return 0;
77 }
prim
原文地址:https://www.cnblogs.com/WDKER/p/5464960.html