MST_prim

关于最小生成树,在本blog的MST_kruskal算法中已经介绍过了,这里介绍另外一种算法即prim算法

写讲一下prim算法的基本思想

1.初始化所有结点都为未访问

2.从图中任选一点,加入到集合V中并标记它为已访问

3.从未标记的点中选取到集合V中的顶点中距离最小的,并加入到集合V中,标记它已访问。

4,.重复3步骤直到所有的点都选入到集合V中

这里讲一下上述步骤的实现

1.初始化vis数组为false,数组下标表示结点的编号,设置距离数组dis的值都为inf(不合理的值)。

2.选1结点,标记vis[1]=true,更新距离数组,dis[i] = map[1][i];(这里采用邻接矩阵存图)

3.从距离数组中选dis最小的,假设是k,标记它为访问vis[k]=true,然后以k结点为跳板更新距离数组if(!vis[i]&&dis[i]>map[k][i]) dis[i]=map[k][i]。(是不是和dijkstra算法一样啊,只是多了一个!vis[i],没学过kruskal算法的跳过)

4,重复3步骤直到所有的结点选完(可以设置一个计数器来判断嘛)

下面举个例子讲一下算法的流程


a为原图,f为MST(最小生成树)

1.初始化距离数组dis,标记数组vis.

2.选1结点,设置vis[1]=true,更新距离数组dis[2]=6,dis[3]=1,dis[4]=5

3.选距离最小的3结点,以3结点为跳板更新距离数组,dis[2]本来是6现在有了3可以更新成5了,同理dis[6]=4

相信读者都明白了,这里不继续往下说了,贴下模板

#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 100000
using namespace std;

struct Graph
{
     int vexnum;
     int map[501][501];
};
bool vis[501];
int dis[501],num1;
Graph G;
int prim()
{
     int tem;
     int  result=0;//记录MST的总权值
     int num1;
      memset(vis,false,sizeof(vis));
        vis[1] = true;
        for(int i=2;i<=G.vexnum;i++)
             dis[i]=G.map[1][i];
             num1 = 1;
     while(num1<G.vexnum)
     {
          int min = INF;
         for(int i=1;i<=G.vexnum;i++)//从剩余的点中找到已有的点的集合中距离最小的点
         {
              if(!vis[i]&&dis[i]<min)
              {
                 min = dis[i];
                 tem = i;
              }
         }
         if(min==INF&&num1<G.vexnum) return -1;//可以选的都选完了,但是没全部选进来(就是说明这个图不是连通图)
         result += min;
         vis[tem] = true;
         for(int i=1;i<=G.vexnum;i++)//更新距离
         {
              if(!vis[i]&&dis[i]>G.map[tem][i])
              {
                   dis[i]=G.map[tem][i];
              }
         }
         num1++;
     }
     return result;
}

最后提一点:因为kruskal是选边所以适合于点多边少的图,而prim算法是选点,所以适合点少边多的图。

推荐题目

http://acm.hdu.edu.cn/showproblem.php?pid=3371(晕死,卡重边,用kruskal算法可能超时:点少边多)


import random import heapq # 生成无向图 def generate_graph(n, p): graph = [[0] * n for _ in range(n)] for i in range(n): for j in range(i+1, n): if random.random() < p: graph[i][j] = graph[j][i] = random.randint(1, 10) return graph # Prim算法求最小生成树 def prim(graph): n = len(graph) visited = [False] * n heap = [(0, 0)] mst = [] while heap: weight, node = heapq.heappop(heap) if visited[node]: continue visited[node] = True mst.append((weight, node)) for i in range(n): if not visited[i] and graph[node][i] > 0: heapq.heappush(heap, (graph[node][i], i)) return mst # Kruskal算法求最小生成树 def kruskal(graph): n = len(graph) edges = [] for i in range(n): for j in range(i+1, n): if graph[i][j] > 0: edges.append((graph[i][j], i, j)) edges.sort() parent = list(range(n)) mst = [] for weight, u, v in edges: pu, pv = find(parent, u), find(parent, v) if pu != pv: mst.append((weight, u, v)) parent[pu] = pv return mst def find(parent, x): if parent[x] != x: parent[x] = find(parent, parent[x]) return parent[x] # 生成图 graph = generate_graph(10, 0.6) print(graph) mst_prim = prim(graph) print("Prim算法求最小生成树:", mst_prim) mst_kruskal = kruskal(graph) print("Kruskal算法求最小生成树:", mst_kruskal) # Dijkstra算法求最短路径 def dijkstra(graph, start, end): n = len(graph) dist = [float('inf')] * n dist[start] = 0 visited = [False] * n heap = [(0, start)] while heap: d, u = heapq.heappop(heap) if visited[u]: continue visited[u] = True for v in range(n): if graph[u][v] > 0: if dist[u] + graph[u][v] < dist[v]: dist[v] = dist[u] + graph[u][v] heapq.heappush(heap, (dist[v], v)) return dist[end] # Bellman-Ford算法求最短路代码分析
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值