基本概念:

  树:如果一个无向连通图G中不存在回路,则称图G是一颗树。

  生成树:无向连通图G的一个子图如果是一颗包含了G中所有顶点的树,则称它为图G的生成树。

注意:生成树是图G的极小连通子图,表示在若在图中任添加一条边都将形成一个回路,同样的,若任意去掉一条边都将使图不在连通

  如果在边中加上权值,那么权值最小的生成树即为最小生成树,权值最大的生成树为最大生成树

  

  最小生成树算法:

  由生成树的定义不难知道,BFS或DFS不重复的遍历结果就是一个生成树。通常情况下,我们都是要求最小生成树的。求最小生成树的算法有三种:Kruskal算法,Boruvka算法,Prime算法。常用的是Kruskal算法和Prime算法。

 

  Kruskal算法核心思想:作用与边,每次选取当前可用最小权值的边。

Kruskal算法有两个注意的地方:① 当前可用,即若某边的权值最小,但它关联的两个顶点本省已经在同一个集合里了也是不可选的。

               ② 最小权值,这个是必须的,不多说。

 

  Prime算法核心思想:作用与顶点,通过选择当前可用的最小权值的边把其他顶点加入到生成树当中。

算法过程:

1.将一个图的顶点分为两部分,一部分是最小生成树中的结点(A集合),另一部分是未处理的结点(B集合)。

2.首先选择一个结点,将这个结点加入A中,然后,对集合A中的顶点遍历,找出A中顶点关联的边权值最小的那个B中的结点(设为v),将此顶点从B中删除,加入集合A中。

3.重复步骤2,直到B集合中的结点为空,结束此过程。

4.A集合中的结点就是由Prime算法得到的最小生成树的结点,依照步骤2的结点连接这些顶点,得到的就是这个图的最小生成树。

代码:

 1 int mat[N][N];
 2 int lowcost[N];
 3 int pre[N];
 4 int n, m;
 5 bool used[N];
 6 
 7 int Prime(int s)
 8 {
 9     for(int i=1; i<=n; i++)
10         lowcost[i] = mat[s][i], pre[i]=s;
11     used[s] = true;
12     lowcost[s] = 0;
13     int mst=0, cnt=0;
14     for(int i=1; i<n; i++)
15     {
16         int tmp=INF, k;
17         for(int j=1; j<=n; j++)
18             if(!used[j] && lowcost[j]<tmp)
19                 tmp = lowcost[k=j];
20         if(tmp==INF) break;
21         used[k] = true;
22         // 输出最小生成树中边
23         printf("%d %d %d\n", k, pre[k], lowcost[k]);
24         mst += tmp;
25         if(++cnt ==n-1) break;
26         for(int j=1; j<=n; j++)
27             if(!used[j] && mat[k][j] < lowcost[j])
28                 lowcost[j] = mat[k][j], pre[j]=k;
29     }
30     return mst;
31 }
View Code

相关文章:

  • 2021-10-25
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-11
  • 2021-06-07
  • 2021-12-04
  • 2021-07-04
猜你喜欢
  • 2021-11-14
  • 2021-05-19
  • 2021-11-14
  • 2022-12-23
  • 2021-04-04
  • 2022-02-19
  • 2021-08-10
相关资源
相似解决方案