最小生成树模板

prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。

一、 普利姆算法(prim)

 1 // 可以输出最短路中的边
 2 #define inf 0x3f3f3f3f
 3 int n,mindis;  //n个顶点 
 4 int map[1000][1000];    // 边的权值 
 5 int vis[1000];          // 标记变量 1表示此下标的顶点已经加入生成树 
 6 int dis[1000];          // 出发点到该下标的权值 
 7 void prim()
 8 {
 9     int i,j,mindis = 0,min,pos;
10     for(i = 1; i <= n; i ++)
11     {
12         dis[i] = map[1][i];
13         vis[i] = 1;
14     }
15     vis[1] = -1;   // 起点已经加入生成树 
16     for (i = 1; i < n; i ++)  // 循环除起点外的其他顶点 
17     {
18         min = inf; pos = -1;
19         for (j = 1; j <= n; j ++)        // 寻找最小权值 
20         {
21             if (vis[j] != -1 && dis[j] < min) 
22             {
23                 min = dis[j];
24                 pos = j;
25             }
26         }
27         if (pos != -1)
28         {
29         //    printf("%d  %d
",vis[pos],pos);    // 输出加入最短路的边 
30             mindis += min;
31             vis[pos] = -1;       // 标记 
32             for (j = 1; j <= n; j ++)     // 更新权值 
33                 if (vis[j]!=-1 && dis[j] > map[pos][j])
34                 {
35                     dis[j] = map[pos][j];
36                     vis[j] = pos;
37                 }
38         }
39         
40     }
41     printf("%d
",mindis);
42 }
 1 // 只计算最小生成树的权值,不输出构成最小生成树的边,可以将dis数组和vis数组合并
 2 #define inf 0x3f3f3f3f
 3 int map[100][100];
 4 int dis[100];
 5 int n;
 6 void prim()   // 起始点为 1 
 7 {
 8     int i,j,pos,min,sum = 0;
 9     for (i = 1; i <= n; i ++)
10         dis[i] = map[1][i];
11     dis[1] = -1;
12     for (i = 1; i < n; i ++)
13     {
14         min = inf; pos = -1;
15         for (j = 1; j <= n; j ++)
16         {
17             if (dis[j] != -1 && dis[j] < min)
18             {
19                 pos = j;
20                 min = dis[j];
21             }
22         }
23         sum += min;
24         dis[pos] = -1;
25         for (j = 1; j <= n; j ++)
26         {
27             if (map[pos][j] < dis[j])
28                 dis[j] = map[pos][j];    
29         } 
30     }
31     printf("%d
",sum);
32 }

一、 克鲁斯卡尔算法(kruskal)

 1 struct point
 2 {
 3     int x,y,l;
 4 }p[11000];
 5 int parent[110],n;
 6 int x[110],y[110];   // 存放边的顶点 
 7 bool cmp(point a, point b)
 8 {
 9     return a.l < b.l;
10 }
11 int find(int x)   // 寻找根节点 
12 {
13     int s,tmp;
14     for (s = x; parent[s] >= 0; s = parent[s]);
15     while (s != x)   // 路径压缩 使后面的查找更快速 
16     {
17         tmp = parent[x];
18         parent[x] = s;
19         x = tmp;
20     }
21     return s;
22 }
23 void Union(int A, int B)   // 将两个不同集合的元素合并,使两个集合中任意两个元素都连通 
24 {
25     int a = find(A), b = find(B);
26     int tmp = parent[a]+parent[b];   // 和为负数 
27     if (parent[a] < parent[b])
28     {
29         parent[b] = a;
30         parent[a] = tmp;
31     }
32     else
33     {
34         parent[a] = b;
35         parent[b] = tmp;
36     }
37 } 
38 void kruskal(int 边数)
39 {
40     int sum = 0;
41     int u,v,i,j = 0;
42     sort(p,p+边数,cmp);
43     memset(parent,-1,sizeof(parent));
44     for (i = 0; i <= k; i ++)
45     {
46         u = p[i].x;    v = p[i].y;
47         if (find(u) != find(v))
48         {
49             sum += p[i].l;
50             Union(u,v);
51             j ++;
52         }
53         if (j == n-1) break;
54     }
55     printf("%d
",sum);
56 }

算法理解: http://www.cnblogs.com/yoke/p/6506492.html

原文地址:https://www.cnblogs.com/yoke/p/6506307.html