数据结构 | 图 | prim算法

prim基本思想

普里姆方法的基本思想是:在图中任取一个顶点K作为开始点,令U={k},W=V-U,其中V为图中所有顶点集,然后找一个顶点在U中,另一个顶点在W中的边中最短的一条,找到后,将该边作为最小生成树的树边保存起来,并将该边顶点全部加入U集合中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离, 使之保持最小,再重复此过程,直到W为空集止。
在这里插入图片描述代码如下:

public class PrimeTest {
	图,可以这样认为:图的任意两个顶点之间都有边,两顶点无法到达的,可以认为他们之间的边权是无穷大
	 static int graph[][]= {{99,6,1,5,99,99},
		       {6,99,5,99,3,99},
		       {1,5,99,5,6,4},
		       {5,99,5,99,99,2},
		       {99,3,6,99,99,6},
		       {99,99,4,2,6,99}};
	 public static void getQuan()
	 {
		 boolean[] visited = new boolean[6];
			for(int i = 0; i < 6; i++){
				visited[i] = false;
			}
		 int sum=0;
		 int index=0;
		 visited[0]=true;//从1这个顶点开始
		 int distance[]=new int[6];
		 for(int j=0;j<6;j++)
		 {
			 distance[j]=graph[0][j];
		 }
		 for(int i=0;i<5;i++)
		 {
			 int min=99;
			 for(int j=0;j<6;j++)
			 {
				 if(visited[j]==false&&distance[j]<min)
				 {
					 min=distance[j];
					 index=j;
				 }
			 }
			 sum+=min;
			 visited[index]=true;
			 for(int j=0;j<6;j++)
			 {
				 if(visited[j]==false&&distance[j]>graph[index][j])
				 {
					 distance[j]=graph[index][j];
					 //更新距离,上面又新产生了一个访问过的节点,现在更新所有未访问节点到所有已经访问节点的最小距离
				 }
			 }
		 }
		System.out.println(sum);
	 }
		       
		     

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Prim算法是一种用于解决最小生成树问题的贪心算法。它的基本思想是从的某个顶点开始,不断选择与当前生成树相邻的、权值最小的边,直到生成一棵包含中所有顶点的最小生成树。 以下是Prim算法的基本步骤: 1. 选择任意一个顶点作为起始点,将该顶点加入到已经生成的树中。 2. 以已经生成的树中的所有顶点为起点,遍历它们所能到达的所有未加入到已经生成的树中的顶点,找到其中权值最小的边。 3. 将找到的权值最小的边所连接的顶点加入到已经生成的树中。 4. 重复步骤2和步骤3,直到生成一棵包含中所有顶点的最小生成树。 下面是Prim算法的C++实现代码: ```c++ #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int N = 100010, INF = 0x3f3f3f3f; int n, m; int h[N], e[N], ne[N], w[N], idx; bool st[N]; int dist[N]; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ; } int prim() { memset(dist, 0x3f, sizeof dist); dist[1] = 0; int res = 0; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> q; q.push({0, 1}); while (q.size()) { auto t = q.top(); q.pop(); int ver = t.second, distance = t.first; if (st[ver]) continue; st[ver] = true; res += distance; for (int i = h[ver]; ~i; i = ne[i]) { int j = e[i]; if (dist[j] > w[i]) { dist[j] = w[i]; q.push({dist[j], j}); } } } return res; } int main() { memset(h, -1, sizeof h); cin >> n >> m; while (m -- ) { int a, b, c; cin >> a >> b >> c; add(a, b, c), add(b, a, c); } cout << prim() << endl; return 0; } ``` 其中,h数组用于存放每个顶点的第一条边的编号,e数组和ne数组分别存放边的终点和下一条边的编号,w数组存放边的权值,idx表示边的数量。st数组表示一个顶点是否已经加入到了已经生成的树中,dist数组存放当前顶点到已经生成的树中的最短距离。优先队列q用于存放每个顶点到已经生成的树中的最短距离,每次从q中取出距离最小的顶点加入到已经生成的树中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值